计算列 R 中出现次数的相似度
Count similarity of occurances across columns R
我有以下数据
df <- data.frame(
group = c('r1','r2','r3','r4'),
X1 = c('A','B','C','K'),
X2 = c('A','C','M','K'),
X3 = c('D','A','C','K')
)
> df
group X1 X2 X3
1 r1 A A D
2 r2 B C A
3 r3 C M C
4 r4 K K K
我想根据 X1
、X2
和 X3
列估算 'similarity score'。例如,在 group
r1(或第 1 行)中,3 个元素中有 2 个相似,因此得分为 2/3 (~67%)。而 group
r4(或第 4 行),得分为 3/3 (100%)。期望的结果如下
> df
group X1 X2 X3 similarity_score
1 r1 A A D .67
2 r2 B C A .33
3 r3 C M C .67
4 r4 K K K 1
我怎样才能做到这一点?
你可以
df$similarity <- round(apply(df[-1], 1, function(x) max(table(x))/length(x)), 2)
df
#> group X1 X2 X3 similarity
#> 1 r1 A A D 0.67
#> 2 r2 B C A 0.33
#> 3 r3 C M C 0.67
#> 4 r4 K K K 1.00
由 reprex package (v2.0.1)
于 2022-04-18 创建
一个tidyverse解决方案:
library(tidyverse)
df %>%
rowwise() %>%
mutate(
similarity_score = max(colMeans(outer(c_across(-group), c_across(-group), `==`)))
)
或者代替 c_across
,你可以做一个 nest
解决方案:
df %>%
group_by(group) %>%
nest(data = -group) %>%
rowwise() %>%
mutate(
similarity_score = max(colMeans(outer(unlist(data), unlist(data), `==`)))
) %>%
unnest(data)
group X1 X2 X3 similarity_score
<chr> <chr> <chr> <chr> <dbl>
1 r1 A A D 0.667
2 r2 B C A 0.333
3 r3 C M C 0.667
4 r4 K K K 1
另一种可能的解决方案:
library(dplyr)
df %>%
rowwise %>%
mutate(score = max(prop.table(table(c_across(X1:X3))))) %>%
ungroup
#> # A tibble: 4 × 5
#> group X1 X2 X3 score
#> <chr> <chr> <chr> <chr> <dbl>
#> 1 r1 A A D 0.667
#> 2 r2 B C A 0.333
#> 3 r3 C M C 0.667
#> 4 r4 K K K 1
或更短:
library(tidyverse)
df %>% mutate(score = pmap_dbl(across(X1:X3), ~ max(prop.table(table(c(...))))))
作为另一种选择,我们可以一次存储所有出现的事件(而不是按行操作):
tab = table(rep(df[, 1], ncol(df) - 1), as.matrix(df[, -1]))
然后,检索每行最多元素的比例:
tab = tab / rowSums(tab)
tab[cbind(1:nrow(df), max.col(tab))]
#[1] 0.6666667 0.3333333 0.6666667 1.0000000
另一种可能的选择,首先旋转更长的时间来总结然后加入数据框。
library(tidyverse)
df %>%
left_join(pivot_longer(., -group) %>%
group_by(group) %>%
summarise(score = round(max(table(value))/length(value), 2)))
输出
group X1 X2 X3 score
1 r1 A A D 0.67
2 r2 B C A 0.33
3 r3 C M C 0.67
4 r4 K K K 1.00
这是 R 基的另一种方式:
df$score <- round(sapply(apply(df[,c(2:4)], 1, table), first) / 3, 2)
# group X1 X2 X3 similarity_score
# 1 r1 A A D 0.67
# 2 r2 B C A 0.33
# 3 r3 C M C 0.67
# 4 r4 K K K 1.00
我有以下数据
df <- data.frame(
group = c('r1','r2','r3','r4'),
X1 = c('A','B','C','K'),
X2 = c('A','C','M','K'),
X3 = c('D','A','C','K')
)
> df
group X1 X2 X3
1 r1 A A D
2 r2 B C A
3 r3 C M C
4 r4 K K K
我想根据 X1
、X2
和 X3
列估算 'similarity score'。例如,在 group
r1(或第 1 行)中,3 个元素中有 2 个相似,因此得分为 2/3 (~67%)。而 group
r4(或第 4 行),得分为 3/3 (100%)。期望的结果如下
> df
group X1 X2 X3 similarity_score
1 r1 A A D .67
2 r2 B C A .33
3 r3 C M C .67
4 r4 K K K 1
我怎样才能做到这一点?
你可以
df$similarity <- round(apply(df[-1], 1, function(x) max(table(x))/length(x)), 2)
df
#> group X1 X2 X3 similarity
#> 1 r1 A A D 0.67
#> 2 r2 B C A 0.33
#> 3 r3 C M C 0.67
#> 4 r4 K K K 1.00
由 reprex package (v2.0.1)
于 2022-04-18 创建一个tidyverse解决方案:
library(tidyverse)
df %>%
rowwise() %>%
mutate(
similarity_score = max(colMeans(outer(c_across(-group), c_across(-group), `==`)))
)
或者代替 c_across
,你可以做一个 nest
解决方案:
df %>%
group_by(group) %>%
nest(data = -group) %>%
rowwise() %>%
mutate(
similarity_score = max(colMeans(outer(unlist(data), unlist(data), `==`)))
) %>%
unnest(data)
group X1 X2 X3 similarity_score
<chr> <chr> <chr> <chr> <dbl>
1 r1 A A D 0.667
2 r2 B C A 0.333
3 r3 C M C 0.667
4 r4 K K K 1
另一种可能的解决方案:
library(dplyr)
df %>%
rowwise %>%
mutate(score = max(prop.table(table(c_across(X1:X3))))) %>%
ungroup
#> # A tibble: 4 × 5
#> group X1 X2 X3 score
#> <chr> <chr> <chr> <chr> <dbl>
#> 1 r1 A A D 0.667
#> 2 r2 B C A 0.333
#> 3 r3 C M C 0.667
#> 4 r4 K K K 1
或更短:
library(tidyverse)
df %>% mutate(score = pmap_dbl(across(X1:X3), ~ max(prop.table(table(c(...))))))
作为另一种选择,我们可以一次存储所有出现的事件(而不是按行操作):
tab = table(rep(df[, 1], ncol(df) - 1), as.matrix(df[, -1]))
然后,检索每行最多元素的比例:
tab = tab / rowSums(tab)
tab[cbind(1:nrow(df), max.col(tab))]
#[1] 0.6666667 0.3333333 0.6666667 1.0000000
另一种可能的选择,首先旋转更长的时间来总结然后加入数据框。
library(tidyverse)
df %>%
left_join(pivot_longer(., -group) %>%
group_by(group) %>%
summarise(score = round(max(table(value))/length(value), 2)))
输出
group X1 X2 X3 score
1 r1 A A D 0.67
2 r2 B C A 0.33
3 r3 C M C 0.67
4 r4 K K K 1.00
这是 R 基的另一种方式:
df$score <- round(sapply(apply(df[,c(2:4)], 1, table), first) / 3, 2)
# group X1 X2 X3 similarity_score
# 1 r1 A A D 0.67
# 2 r2 B C A 0.33
# 3 r3 C M C 0.67
# 4 r4 K K K 1.00