【问题标题】:get max value per id, then only value per id R获取每个 id 的最大值,然后只获取每个 id R 的值
【发布时间】:2013-08-19 18:10:33
【问题描述】:

我想根据每个人每个日期的最大数量,通过每个人每个日期只进行一次观察来缩小我的 df。

这是我的 df:

names      dates quantity
1    tom 2010-02-01       28
3    tom 2010-03-01        7
2   mary 2010-05-01       30
6    tom 2010-06-01       21
4   john 2010-07-01       45
5   mary 2010-07-01       30
8   mary 2010-07-01       28
11   tom 2010-08-01       28
7   john 2010-09-01       28
10  john 2010-09-01       30
9   john 2010-07-01       45
12  mary 2010-11-01       28
13  john 2010-12-01        7
14  john 2010-12-01       14

我首先通过找到每个人每个日期的最大数量来做到这一点。这没问题,但正如您所看到的,如果一个人的数量相等,他们每个日期保留相同数量的 obs。

merge(df, aggregate(quantity ~ names+dates, df, max))



 names      dates quantity
1   john 2010-07-01       45
2   john 2010-07-01       45
3   john 2010-09-01       30
4   john 2010-12-01       14
5   mary 2010-05-01       30
6   mary 2010-07-01       30
7   mary 2010-11-01       28
8    tom 2010-02-01       28
9    tom 2010-03-01        7
10   tom 2010-06-01       21
11   tom 2010-08-01       28

所以,我的下一步是只取每个日期的第一个 obs(鉴于我已经选择了最大的数量)。我无法得到正确的代码。这是我尝试过的:

merge(l, aggregate(names ~ dates, l, FUN=function(z) z[1]))->m  ##doesn't get rid of one obs for john

还有一个 data.table 选项

l[, .SD[1], by=c(names,dates)]  ##doesn't work at all

我喜欢聚合和 data.table 选项,因为它们速度很快,并且 df 有大约 100k 行。

提前感谢您!

解决方案

我发的太快了——抱歉!!解决这个问题的一个简单方法就是找到重复项,然后删除它们。例如。,;

merge(df, aggregate(quantity ~ names+dates, df, max))->toy
toy$dup<-duplicated(toy)
toy<-toy[toy$dup!=TRUE,]

这里是系统时间

 system.time(dt2[, max(new_quan), by = list(hai_dispense_number, date_of_claim)]->method1)
   user  system elapsed 
  20.04    0.04   20.07 



 system.time(aggregate(new_quan ~ hai_dispense_number+date_of_claim, dt2, max)->rpp)
   user  system elapsed 
 19.129   0.028  19.148 

【问题讨论】:

  • 您应该将您的解决方案作为答案发布并接受它,而不是将其包含在您的问题中。
  • @user2363642 有一个更好的方法,使用unique()。请参考下面我的回答。
  • 我可以接受我自己的答案吗?这合乎道德吗?!
  • 如果你能证明它比其他所有的都快,那么它就是“道德的”。我认为我们仍在等待真正的 data.table 解决方案,它很可能会获胜。 (我怀疑这是重复的。)
  • 我也不明白合并在做什么。为什么不只是:aggregate(quantity ~ names+dates, df, max)

标签: r aggregate data.table


【解决方案1】:

这是data.table 解决方案:

dt[, max(quantity), by = list(names, dates)]

替补:

N = 1e6

dt = data.table(names = sample(letters, N, T), dates = sample(LETTERS, N, T), quantity = rnorm(N))
df = data.frame(dt)

op = function(df) aggregate(quantity ~ names+dates, df, max) 
eddi = function(dt) dt[, max(quantity), by = list(names, dates)]

microbenchmark(op(df), eddi(dt), times = 10)
#Unit: milliseconds
#     expr      min        lq   median        uq      max neval
#   op(df) 2535.241 3025.1485 3195.078 3398.4404 3533.209    10
# eddi(dt)  148.088  162.8073  198.222  220.1217  286.058    10

【讨论】:

  • 查看系统时间,我会在上面发布,这样更容易看到
  • @user2363642 是的,aggregate 也足够快 - 在我的测试中,data.table 有点快,你在单次运行的噪音中看不到,但仍然aggregate 这里的速度给我留下了深刻的印象
  • @user2363642 hmm 在重新测试 aggregate 时要慢得多(我意识到我正在测试一个非常小的样本),请参阅编辑
  • 很棒的对话和方法交流。高兴极了。谢谢大家!
  • @user2363642 你可以在上面的长凳上看到尺寸,并可以尝试使用它 - 在 89000 行时,它仍然快 20 倍左右;我现在想不出为什么aggregate 会在您的数据速度上遥遥领先
【解决方案2】:

我不确定这会给你想要的输出,但它肯定会处理“重复行”:

 # Replicating your dataframe
 df <- data.frame(names = c("tom", "tom", "mary", "tom", "john", "mary", "mary", "tom", "john", "john", "john", "mary", "john", "john"), dates = c("2010-02-01","2010-03-01", "2010-05-01", "2010-06-01", "2010-07-01", "2010-07-01", "2010-07-01", "2010-08-01", "2010-09-01", "2010-09-01", "2010-07-01", "2010-11-01", "2010-12-01", "2010-12-01"), quantity = c(28,7,30,21,45,30,28,28,28,30,45,28,7,14)) 

 temp = merge(df, aggregate(quantity ~ names+dates, df, max))
 df.unique = unique(temp)

【讨论】:

    【解决方案3】:

    如果你使用的是data.frame,

     library(plyr)
        ddply(mydata,.(names,dates),summarize, maxquantity=max(quantity))
    

    【讨论】:

    • 嗨 Metrics,谢谢。一步完成我想要的,而不是两步。我唯一担心的是 ddply 将需要很长时间来处理我庞大的 df(约 100K 行)。请参阅上面的编辑。
    【解决方案4】:
    do.call( rbind, 
            lapply( split(df, df[,c("names","dates") ]), function(d){
                                             d[which.max(d$quantity), ] } )
            )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 2014-09-12
      • 2010-10-19
      • 2021-01-30
      • 2016-02-16
      • 1970-01-01
      • 2020-10-01
      相关资源
      最近更新 更多