【问题标题】:Finding the index of the maximum value by group for a data.table in RR中的data.table按组查找最大值的索引
【发布时间】:2014-08-15 03:48:06
【问题描述】:

我有一个如下所示的 data.table 或 data.frame:

Name     Person     Date
A        1          1/1/2004
A        2          1/1/2004
A        2          1/3/2004
A        3          1/1/2004
A        3          1/3/2004
A        3          1/9/2004
B        4          1/7/2004
B        5          1/7/2004
B        5          1/10/2004
B        6          1/7/2004
B        6          1/10/2004
B        6          1/17/2004

在这里,我正在尝试创建一个新的数据表,其中包含日期的“NA”,如果它们不是每个人的最大值。基本上,我试图让数据表看起来像:

    Name     Person     Date
A        1          1/1/2004
A        2          "NA"
A        2          1/3/2004
A        3          "NA"
A        3          "NA"
A        3          1/9/2004
B        4          1/7/2004
B        5          "NA"
B        5          1/10/2004
B        6          "NA"
B        6          "NA"
B        6          1/17/2004

基本上,我想到的算法是按人查看每个分组。如果按人分组只有一个元素,则该值是最大值,因此我们让它留在那里。但是,例如,在按人 2 分组时,最大值是 2004 年 1 月 3 日,所以我们让 2004 年 1 月 1 日为“NA”。

我能想到的唯一方法是按组(Person)找到与最大值对应的数据表的索引,然后创建一个所有NA的新向量,然后用最大值的索引替换价值观。

代码如下:

which.max(data$Date, by=data$Person)

不知何故,这对我不起作用,但无论哪种方式,这段代码看起来都可能很耗时,尤其是当我的数据集是 1 亿行时。大型数据集是否会有快速实现,尤其是在 data.table 包中工作?谢谢!

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    使用data.table:

    #dat <- as.data.table(dat)
    #dat$Date <- as.Date(dat$Date,format="%m/%d/%Y")
    dat[dat[, Date != max(Date) , by=Person][,V1], Date := NA]
    dat
    
     #   Name Person       Date
     #1:    A      1 2004-01-01
     #2:    A      2       <NA>
     #3:    A      2 2004-01-03
     #4:    A      3       <NA>
     #5:    A      3       <NA>
     #6:    A      3 2004-01-09
     #7:    B      4 2004-01-07
     #8:    B      5       <NA>
     #9:    B      5 2004-01-10
    #10:    B      6       <NA>
    #11:    B      6       <NA>
    #12:    B      6 2004-01-17
    

    【讨论】:

      【解决方案2】:

      这是ave() 的一个很好的用例,它允许您将函数应用于每个人的值。如果这是您的示例数据

      dd<-structure(list(Name = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 
          2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"), 
          Person = c(1L, 2L, 2L, 3L, 3L, 3L, 4L, 5L, 5L, 6L, 6L, 6L
          ), Date = structure(c(12418, 12418, 12420, 12418, 12420, 
          12426, 12424, 12424, 12427, 12424, 12427, 12434), class = "Date")), 
          .Names = c("Name", "Person", "Date"), 
          row.names = c(NA, -12L), class = "data.frame")
      

      然后使用

      with(dd, ave(Date, Person,FUN=function(x) {x[x!=max(x)]<-NA; x}))
      #  [1] "2004-01-01" NA           "2004-01-03" NA           NA          
      #  [6] "2004-01-09" "2004-01-07" NA           "2004-01-10" NA          
      # [11] NA           "2004-01-17"
      

      【讨论】:

        【解决方案3】:

        使用data.table 的另一种方式(假设每个组没有多个最大值)

         dat[dat[, order(Date)!=.N, by=Person]$V1, Date:= NA]
         dat
         #   Name Person       Date
         #1:    A      1 2004-01-01
         #2:    A      2       <NA>
         #3:    A      2 2004-01-03
         #4:    A      3       <NA>
         #5:    A      3       <NA>
         #6:    A      3 2004-01-09
         #7:    B      4 2004-01-07
         #8:    B      5       <NA>
         #9:    B      5 2004-01-10
        #10:    B      6       <NA>
        #11:    B      6       <NA>
        #12:    B      6 2004-01-17
        

        如果您有多个最大值:

        dat[dat[, rank(Date,ties.method="max")!=.N, by=Person]$V1, Date:=NA]
        

        格式化date

        dat[dat[, order(Date)!=.N, by=Person]$V1, Date:= NA][,Date:=format(Date, "%m/%d/%Y")]
        

        【讨论】:

        • 与仅计算 max 相比,order(或 rank)每个组的观察在计算上的要求非常高。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多