如何计算任意两个给定值在 R 中连续出现的次数?

How do I count the number of times any two given values occur together in a row in R?

我正在使用这样的数据框,ID 列表示特定的出版物:

ID AuthorA AuthorB AuthorC
1   Chris   Lee     Jill
2   Jill    Tom     Lee 
3   Tom     Chris   Lee
4   Lee     Jill    NA
5   Jill    Chris   NA

我想为社交网络分析生成 sourcetargetcount 列。换句话说,计算两位作者出现在同一出版物上的次数。然而,我正在使用的数据框有 18 个作者列。这应该是最终输出:

Source Target Count
Chris   Lee     2
Chris   Jill    2
Lee     Jill    3
Jill    Tom     1
Tom     Lee     2
Tom     Chris   1

对于每一行,您可以创建名称的所有组合并使用 table 计算它们的频率。

result <- stack(table(unlist(apply(df[-1], 1, function(x) {
                 vec <- na.omit(x)
                 if(length(vec) < 2) return(NULL)
                  combn(vec, 2, function(y) paste0(sort(y), collapse = '-'))
            }))))[2:1]
result
#         ind values
#1 Chris-Jill      2
#2  Chris-Lee      2
#3  Chris-Tom      1
#4   Jill-Lee      3
#5   Jill-Tom      1
#6    Lee-Tom      2

要将它们放在单独的列中,您可以使用 separate :

tidyr::separate(result, ind, c('Source', 'Target'), sep = '-')

#  Source Target values
#2  Chris   Jill      2
#3  Chris    Lee      2
#4  Chris    Tom      1
#6   Jill    Lee      3
#7   Jill    Tom      1
#9    Lee    Tom      2

这是 base R 中的另一种方法。它涉及使用 crossprod 获取您想要的频率,而不是您想要的格式。

下面是 crossprod 输出的示例:

crossprod(table(cbind(1:nrow(m), stack(lapply(m[, -1], as.character)))[, 1:2]))
#        values
# values  Chris Jill Lee Tom
#   Chris     3    2   2   1
#   Jill      2    4   3   1
#   Lee       2    3   4   2
#   Tom       1    1   2   2

查看上面的内容,您可以看到您感兴趣的值位于结果矩阵的上三角或下三角中。您可以使用此信息编写如下函数,以按值对获取表格:

pair_table <- function(data) {
  m <- cbind(1:nrow(data), stack(lapply(data, as.character)))
  count <- crossprod(table(m[, 1:2]))
  count[upper.tri(count, diag = TRUE)] <- NA
  na.omit(as.data.frame(as.table(count)))
}

使用函数:

pair_table(m[, -1])
#    values values.1 Freq
# 2    Jill    Chris    2
# 3     Lee    Chris    2
# 4     Tom    Chris    1
# 7     Lee     Jill    3
# 8     Tom     Jill    1
# 12    Tom      Lee    2

此答案中使用的样本数据。

 m <- structure(list(ID = 1:5, AuthorA = structure(c(1L, 2L, 4L, 3L,                       
     2L), .Label = c("Chris", "Jill", "Lee", "Tom"), class = "factor"),                    
         AuthorB = structure(c(3L, 4L, 1L, 2L, 1L), .Label = c("Chris",                    
         "Jill", "Lee", "Tom"), class = "factor"), AuthorC = structure(c(1L,               
         2L, 2L, NA, NA), .Label = c("Jill", "Lee"), class = "factor")), row.names = c(NA, 
     5L), class = "data.frame")