[英]More efficient way to calculate runs in subgroups
我正在尋找在數據框中添加一列,該列針對列組合的子集中的每個元素寫入該元素的等級。
下面的代碼解決了這個問題,但是我希望以一種內存和CPU效率更高的方式來實現。
## using the plyr package
library(plyr)
## example data
var1 = c(1,1,1,1,2,2,1,5,6,7,1,9,10)
var2 = c("a","a","a","b","b", "b","c","c","c","c","a","a","a" )
ex1 <- data.frame( var1, var2 )
## easy but inefficient solution
ex2 <- ddply( ex1, c("var1", "var2"), transform, run = 1:length(var1) )
print(ex2)
輸出看起來像這樣(這就是我想要的)
"var1" "var2" "run"
1 "a" 1
1 "a" 2
1 "a" 3
1 "a" 4
1 "b" 1
1 "c" 1
2 "b" 1
2 "b" 2
5 "c" 1
6 "c" 1
7 "c" 1
9 "a" 1
10 "a" 1
組合var1 == 1和var2 ==“ a”出現了4次。 在該子組中,ddply計算每個元素的等級,並將等級保存在該元素的同一行中。 第一次出現組合run [1]變為“ 1”,第二次出現run [2]變為“ 2”,依此類推...
在我的示例中,結果由ddply函數重新排序,但這並不重要。
您可以像這樣使用dplyr
來做到這一點:
require(dplyr)
ex1 %>% group_by(var1, var2) %>% mutate(run = 1:n()) %>% arrange(var1, var2)
# var1 var2 run
#1 1 a 1
#2 1 a 2
#3 1 a 3
#4 1 a 4
#5 1 b 1
#6 1 c 1
#7 2 b 1
#8 2 b 2
#9 5 c 1
#10 6 c 1
#11 7 c 1
#12 9 a 1
#13 10 a 1
arrange
只是按照您期望的結果順序進行。
我認為這是可以使用data.table
但是我不確定這是否是最慣用的data.table方法:
require(data.table)
setDT(ex1)[,run:=1:.N, by=list(var1, var2)]
# var1 var2 run
#1: 1 a 1
#2: 1 a 2
#3: 1 a 3
#4: 1 b 1
#5: 2 b 1
#6: 2 b 2
#7: 1 c 1
#8: 5 c 1
#9: 6 c 1
#10: 7 c 1
#11: 1 a 4
#12: 9 a 1
#13: 10 a 1
正如@DavidArenburg在其評論中建議的那樣,最好使用:
setDT(ex1)[,run:=seq_len(.N), by=list(var1, var2)]
用於data.table
方法。 感謝您的評論!
ave
為此工作:
ex1$run <- ave(ex1$var1, list(ex1$var1, ex1$var2), FUN=seq_along)
ex1
var1 var2 run
1 1 a 1
2 1 a 2
3 1 a 3
4 1 b 1
5 2 b 1
6 2 b 2
7 1 c 1
8 5 c 1
9 6 c 1
10 7 c 1
11 1 a 4
12 9 a 1
13 10 a 1
請注意,這些行不會重新排序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.