如何优化大R数据帧中每一行的过滤和计数

时间:2012-04-17 18:23:36

标签: r dataframe apply data.table sqldf

我有一个数据框,例如:

  name day wages
1  Ann   1   100
2  Ann   1   150
3  Ann   2   200
4  Ann   3   150
5  Bob   1   100
6  Bob   1   200
7  Bob   1   150
8  Bob   2   100

对于每个唯一的姓名/日对,我想计算一系列总数,例如“此人当前或次日的工资大于175的次数”。除了工资之外还有更多的列,并且每行的每个总计有四个时间片。

我目前可以通过独特的数据框来完成:

df.unique <- df[!duplicated(df[,c('name','day')]),]

然后对于df.unique中的每一行,将以下函数(为了清晰起见,写得很简单)应用于df

for(i in 1:nrow(df.unique)) {
    df.unique[i,"wages_gt_175_day_and_next"] <- wages_gt_for_person_today_or_next(df,175,df.unique[i,"day"],df.unique[i,"name"])
}

wages_gt_for_person_today_or_next <- function(df,amount,day,person) {
  temp <- df[df$name==person,]
  temp <- temp[temp$day==day|temp$day==day+1,]
  temp <- temp[temp$wages > amount,]
  return(nrow(temp))
}

在这个琐碎的例子中给我:

name day wages_gt_175_day_and_next
Ann   1   1
Ann   2   1
Ann   3   0
Bob   1   1
Bob   2   0

然而,鉴于我有数十万行,这似乎是一种非常缓慢的方法。这样做有更聪明的方法吗?有矩阵运算的东西,apply,sqldf,类似的东西吗?

重新创建示例df的代码:

structure(list(name = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L), .Label = c("Ann", "Bob"), class = "factor"), day = c(1, 
1, 2, 3, 1, 1, 1, 2), wages = c(100, 150, 200, 150, 100, 200, 
150, 100)), .Names = c("name", "day", "wages"), row.names = c(NA, 
-8L), class = "data.frame")

1 个答案:

答案 0 :(得分:3)

简单地从你的示例输出开始,使用data.table这里的东西有点漂亮:

require(data.table)
DT <- data.table(df)
setkey(DT,name,day)

DT[,list(gt175 = sum(wages >= 175)),list(name,day)][,list(day = day,gt175 = as.integer(gt175 + c(tail(gt175,-1),0) > 0)),list(name)]

这有点令人费解,但应该很快。