如何基于大数据框计算共现矩阵?

Seb*_*Seb 5 r large-data plyr dataframe data.table

我想根据这里推荐的代码创建一个共现矩阵(另见下文)。它适用于我使用的大多数数据帧。但是,如果我使用data.table::melt...

negative length vectors are not allowed

...或稍后使用 base::crossprod

error in crossprod: attempt to make a table with >=2^31 elements

两者都与数据帧的大小有关。在第一种情况下,它与行数有关,而在后一种情况下,矩阵的大小超过了限制。

我知道关于第一个问题(解决方案data.table::melt)提出的[2] [3][4] ,以及对于第二个问题(base::crossprod通过)[5][6] ,和我见过[ 7]但我不确定如何使它们适合我的情况。我试图按 ID 将数据帧拆分为几个数据帧,合并它们并计算共现矩阵,但我刚刚产生了额外的错误消息(例如,无法分配大小为 17.8 GB 的向量)。

可重现的例子

我有一个由plyr::join它创建的组装数据框,看起来像这样(但是,当然,要大得多):

df <- data.frame(ID = c(1,2,3,20000), 
                  C1 = c("England", "England", "England", "China"),
                  C2 = c("England", "China", "China", "England"),
                  C5850 = c("England", "China", "China", "England"),
                  SC1 = c("FOO", "BAR", "EAT", "FOO"),
                  SC2 = c("MERCI", "EAT", "EAT", "EAT"),
                  SC5850 = c("FOO", "MERCI", "FOO", "FOO"))

ID      C1      C2      ... C5850    SC1 SC2   ... SC5850
1       England England     England  FOO MERCI     FOO
2       England China       China    BAR EAT       MERCI
3       England China       China    EAT EAT       EAT
200000  China   England     England  FOO EAT       FOO
Run Code Online (Sandbox Code Playgroud)

原始代码

colnames(df) <- c(paste0("SCCOUNTRY", 2:7))

library(data.table)

melt(setDT(df), id.vars = "ID", measure = patterns("^SCCOUNTRY"))[nchar(value) > 0 & complete.cases(value)] -> foo
unique(foo, by = c("ID", "value")) -> foo2
crossprod(table(foo2[, c(1,3)])) -> mymat
diag(mymat) <- ifelse(diag(mymat) <= 1, 0, mymat)
Run Code Online (Sandbox Code Playgroud)

条件(用于计算共生矩阵)

  1. 不考虑按 ID/row 没有附加观察的单个观察,即只有一个国家一次的行被计为 0。
  2. 组合/共现应计为 1。
  3. 处于组合中的结果也算作自组合(USA-USA),即分配值为 1。
  4. 没有超过 1 的值分配给按行/ID 的组合。