如何计算任意两个给定值在 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
我想为社交网络分析生成 source
、target
和 count
列。换句话说,计算两位作者出现在同一出版物上的次数。然而,我正在使用的数据框有 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")
我正在使用这样的数据框,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
我想为社交网络分析生成 source
、target
和 count
列。换句话说,计算两位作者出现在同一出版物上的次数。然而,我正在使用的数据框有 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")