Here's another approach in base R. It involves using crossprod
which gets the frequencies you're after, just not in the format you're after.
Here's an example of what the crossprod
output looks like:
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
Looking at the above, you can see that the values you're interested in are in the upper or lower triangle of the resulting matrix. You can use this information to write a function like the following to get your tabulations by pairs of values:
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)))
}
Using the function:
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
Sample data used in this answer.
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")