Самый быстрый способ взять разницу элементов в data.frame в R - PullRequest
1 голос
/ 31 октября 2019

Используя следующий набор данных, какой самый быстрый способ вычислить для каждого идентификатора (Col1) разницу между всеми другими ID02 (Col2) в одно и то же время (Col3, t) без использования dplyr, (data.table добро пожаловать!)?

Более конкретно, для каждого идентификатора в столбце ID я хотел бы принять все возможные различия между его относительным значением в столбце value и значением в столбце value относительно другогонаблюдения с тем же ID числом (в течение того же года). То есть мне нужен фрейм данных со всеми различиями по парам (ID - ID2) с одинаковыми ID и одинаковыми t.

Набор фиктивных данных:

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 = 1 и ID2 = 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
...   

1 Ответ

3 голосов
/ 31 октября 2019

Это должно быть довольно быстро. Я оставлю любое форматирование и удаление ненужных вам столбцов:

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
# ...
...