在 R 中获取 data.frame 中元素差异的最快方法

Posted

技术标签:

【中文标题】在 R 中获取 data.frame 中元素差异的最快方法【英文标题】:Fastest way to take difference of elements in a data.frame in R 【发布时间】:2020-02-26 20:51:27 【问题描述】:

使用以下数据集,在不使用dplyr、(@ 987654323@欢迎!)?

更具体地说,对于 ID 列中的每个 ID,我想将其在 value 列中的相对值与 value 列中的值相对于其他观察值之间的所有可能差异相同的ID 号码(在同一年内)。也就是说,我想要一个具有相同ID 和相同t 的对(ID-ID2)具有所有差异的数据框。

虚拟数据集是:

df <- data.frame(ID = rep(rep(c(1,2,3,4),3),2), ID2 = rep(c(rep(5,4), rep(6,4), 
                 rep(7,4)),2), t = c(rep(1,12), rep(2,12)), value = runif(12) )


   ID ID2 t     value
1   1   5 1 0.6991799
2   2   5 1 0.0879940
3   3   5 1 0.5876535
4   4   5 1 0.2105821
5   1   6 1 0.9483806
6   2   6 1 0.5076218
7   3   6 1 0.1790157
8   4   6 1 0.5229501
9   1   7 1 0.7365285
10  2   7 1 0.5298920
11  3   7 1 0.6172215
12  4   7 1 0.3365588
13  1   1 2 0.6991799
14  2   5 2 0.0879940
15  3   5 2 0.5876535
16  4   5 2 0.2105821
17  1   6 2 0.9483806
18  2   6 2 0.5076218
19  3   6 2 0.1790157
20  4   6 2 0.5229501
21  1   7 2 0.7365285
22  2   7 2 0.5298920
23  3   7 2 0.6172215
24  4   7 2 0.3365588

应该在value 列上处理差异。然后应该像这样创建新的data.frame,其中第一行中的1(5)指的是ID = 1ID2 = 5在年份t = 1中的行。

   ID    ID2 t     value
1   1(5)   6 1     0.6991799 - 0.9483806
2   1(5)   7 1     0.6991799 - 0.7365285
3   1(6)   7 1     0.9483806 - 0.7365285
4   2(5)   6 1     0.0879940 - 0.5076218
2   2(5)   7 1     0.0879940 - 0.5298920
3   2(6)   7 1     0.5076218 - 0.5298920
...   

【问题讨论】:

你能给我们一个预期输出的样本吗?比破译您对操作的解释更容易。 我的理解是否正确,您想计算跨 t 的不同 ID/ID2 对之间的价值差异?您想如何处理t-组中重复的IDs?例如,请参见第 1、5 和 9 行。它们具有相同的 ID 值。 抱歉解释不佳:我重写了问题并添加了一个示例。谢谢! 对于像runif这样的随机数据,总是set.seed。否则,我们无法复制您的样品。 【参考方案1】:

这应该很快。我会留下任何你不想要的列的格式和删除:

library(data.table)
setDT(df)
setkey(df, ID, t)

# self join on the keys (ID and t)
# then keep only rows where ID2 is less than the joined ID2
result = df[df, allow.cartesian = TRUE][ID2 < i.ID2]
# calculate the difference
result[, diff := value - i.value]
result
#     ID ID2 t     value i.ID2    i.value        diff
#  1:  1   5 1 0.2468819     6 0.34515017 -0.09826830
#  2:  1   5 1 0.2468819     7 0.01068400  0.23619786
#  3:  1   6 1 0.3451502     7 0.01068400  0.33446616
#  4:  1   5 2 0.2468819     6 0.34515017 -0.09826830
#  5:  1   5 2 0.2468819     7 0.01068400  0.23619786
#  6:  1   6 2 0.3451502     7 0.01068400  0.33446616
#  7:  2   5 1 0.1749664     6 0.29682198 -0.12185559
#  8:  2   5 1 0.1749664     7 0.40023788 -0.22527149
#  9:  2   6 1 0.2968220     7 0.40023788 -0.10341590
# 10:  2   5 2 0.1749664     6 0.29682198 -0.12185559
# 11:  2   5 2 0.1749664     7 0.40023788 -0.22527149
# ...

【讨论】:

1 [] 中的另一个类似选项是setorder( DT[DT, on=.(id, t, id2&lt;id2), allow.cartesian=TRUE, nomatch=0L, .(ID=x.ID, x.ID2, ID2=i.ID2, t, value=x.value-i.value)], t, ID, ID2)[] 哈!我从这样的非 equi 自加入开始,但我有 id2 != id2,这是不允许的。然后我改用这种方法,直到我意识到&lt; 更合适,忘记了我可以回到非 equi 连接。谢谢! 谢谢你们!这真的有帮助!很抱歉延迟接受答案!

以上是关于在 R 中获取 data.frame 中元素差异的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从 R data.frame 中获取行

如何从r中的列联表中获取带有案例的data.frame?

如何合并R中列表的所有元素? [复制]

R语言中的 Vector, Array, List 和 Data Frame

R - 如何生成数据框中所有列组合的差异

R中的cor()行为在各个向量和data.frame之间有所不同