使用2列data.table
,我想通过对第2列中共享元素的数量求和来总结第1列中的成对关系。换句话说,每个共享Y元素的数量是多少X值的成对组合具有?
例如,我可以通过两个步骤完成此操作,首先进行笛卡尔交叉连接,然后总结如下:
d = data.table(X=c(1,1,1,2,2,2,2,3,3,3,4,4), Y=c(1,2,3,1,2,3,4,1,5,6,4,5))
setkey(d, Y)
d2 = d[d, allow.cartesian=TRUE]
d2[, .N, by=c("X", "i.X")]
# X i.X N
#1: 1 1 3
#2: 2 1 3
#3: 3 1 1
#4: 1 2 3
#5: 2 2 4
#6: 3 2 1
#7: 1 3 1
#8: 2 3 1
#9: 3 3 3
#10: 4 2 1
#11: 2 4 1
#12: 4 4 2
#13: 4 3 1
#14: 3 4 1
此结果的第二行表示X=1
与X=2
共享3个Y值;而X=3
只与X=4
共享1个y值。
在绕过笛卡尔连接步骤时是否有任何方法可以做到这一点,从而导致表格效率低下?我希望在具有数百万行的表上执行类似的操作,并且笛卡尔连接将进入2^31
向量大小限制(除了变慢)。
我想象这样的事情:
d[d, list(X, length(Y)), by=c("X", "i.X")]
但这会产生错误i.X not found
我可以使用下面的代码在SQL中执行此操作 - 但是无法弄清楚如何将其转换为data.table语法:
CREATE TABLE test (X integer, Y integer);
INSERT INTO test VALUES(1, 1);
INSERT INTO test VALUES(1, 2);
INSERT INTO test VALUES(1, 3);
INSERT INTO test VALUES(2, 1);
INSERT INTO test VALUES(2, 2);
INSERT INTO test VALUES(2, 3);
INSERT INTO test VALUES(2, 4);
INSERT INTO test VALUES(3, 1);
INSERT INTO test VALUES(3, 5);
INSERT INTO test VALUES(3, 6);
INSERT INTO test VALUES(4, 4);
INSERT INTO test VALUES(4, 5);
SELECT A.X, B.X, COUNT(A.Y) as N FROM test as A JOIN test as B WHERE A.Y==B.Y GROUP BY A.X, B.X;
关键是我想要总结的列与我加入的列相同。这个问题与这些问题类似,但并不完全相同:
R Data.Table Join on Conditionals
How to self join a data.table on a condition
关键的区别在于我想汇总索引列,这似乎与= .EACHI无关。
答案 0 :(得分:4)
如果您可以将Y
分成不具有X
的大交集的群组,则可以按这些群组进行计算首先,产生一个较小的中间表:
d[, grp := Y <= 3] # this particular split works best for OP data
d[, .SD[.SD, allow = T][, .N, by = .(X, i.X)], by = grp][,
.(N = sum(N)), by = .(X, i.X)]
上面的中间表只有16行,而不是26行。不幸的是,我无法想出一种自动创建此类分组的简单方法。
答案 1 :(得分:2)
您已经有用SQL编写的解决方案,因此我建议使用R包sqldf
这是代码:
library(sqldf)
result <- sqldf("SELECT A.X, B.X, COUNT(A.Y) as N FROM test as A JOIN test as B WHERE A.Y==B.Y GROUP BY A.X, B.X")