更有效的方法来计算子组中的运行

时间:2014-06-18 13:58:57

标签: r

计算子组中每个元素的等级

我希望在数据框中添加一列,对于列组合的子集中的每个元素,写入该元素的等级。

这有效但效率低下:

下面的代码解决了这个问题,但我希望以更高的内存和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&amp; var2 ==“a”发生了4次。在该子组中,ddply计算每个元素的等级,并将该等级保存在该元素的同一行中。组合第一次运行[1]得到“1”,第二次运行[2]得到“2”等等......

修改

在我的例子中,结果由ddply函数重新排序,但这并不重要。

2 个答案:

答案 0 :(得分:3)

你可以使用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来做到这一点,但我不确定这是否是最惯用的数据。表格方法:

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方法。感谢您的评论!

答案 1 :(得分:2)

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

请注意,行不会重新排序。