我有一个数据框,例如:
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")
答案 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)]
这有点令人费解,但应该很快。