【问题标题】:Conditionally Select Rows within a Group with Data.Table使用 Data.Table 有条件地选择组内的行
【发布时间】:2019-04-14 19:18:03
【问题描述】:

我正在寻找使用 data.table 的解决方案 ― 我有一个包含以下列的 data.table:

data <- data.frame(GROUP=c(3,3,4,4,5,6),
                    YEAR=c(1979,1985,1999,2011,2012,1994),
                    NAME=c("S","A","J","L","G","A"))

data <- as.data.table(data)

数据表:

GROUP  YEAR    NAME
3      1979    Smith 
3      1985    Anderson
4      1999    James
4      2011    Liam
5      2012    George
6      1994    Adams

对于每个组,我们要使用以下规则选择一行:

  • 如果年份 > 2000,请选择最小年份大于 2000 的行。
  • 如果没有年份 > 2000,则选择最大年份的行。

期望的输出:

GROUP  YEAR    NAME
3      1985    Anderson
4      2011    Liam
5      2012    George
6      1994    Adams

谢谢!我已经为此苦苦挣扎了一段时间。

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    使用dplyr 包我得到了这样的输出(尽管它可能不是最简单的答案):

     library(dplyr)
     library(magrittr)
    
     data <- data.frame(GROUP=c(3,3,4,4,5,6),
                        YEAR=c(1979,1985,1999,2011,2012,1994),
                        NAME=c("S","A","J","L","G","A"))
    
     data %>%
       subset(YEAR < 2000) %>%
       group_by(GROUP) %>%
       summarise(MAX=max(YEAR)) %>%
       join(data %>%
              subset(YEAR > 2000) %>%
              group_by(GROUP) %>%
              summarise(MIN=min(YEAR)), type="full") %>%
       mutate(YEAR=ifelse(is.na(MIN), MAX, MIN)) %>%
       select(c(GROUP, YEAR)) %>%
       join(data)
    

    结果:

       GROUP YEAR NAME
          3  1985   A
          4  2011   L
          5  2012   G
          6  1994   A
    

    编辑:对不起,我的第一个答案没有考虑最小/最大条件。希望这会有所帮助

    【讨论】:

    • 感谢 tidyverse 解决方案!以及格式化指针。
    【解决方案2】:

    如果您将特殊的.I 行计数器子集化,data.table 应该会简单得多:

    library(data.table)
    setDT(data)
    data[
      data[
            ,
            if(any(YEAR > 2000)) 
               .I[which.min(2000 - YEAR)] else
               .I[which.max(YEAR)],
            by=GROUP
          ]$V1
    ]
    #   GROUP YEAR NAME
    #1:     3 1985    A
    #2:     4 2011    L
    #3:     5 2012    G
    #4:     6 1994    A
    

    感谢@r2evans 提供背景信息 -

    .I 是一个等价于seq_len(nrow(x)) 的整数向量。
    参考: http://rdrr.io/cran/data.table/man/special-symbols.html

    所以,我在这里所做的只是为每个by= 级别的每个计算获取整个data 的匹配行索引。然后再次使用这些行索引对data 进行子集化。

    【讨论】:

    • 我收到一个错误Error in [.data.frame(data, , if (any(YEAR &gt; 2000)) .I[which.min(2000 - : unused argument (by = GROUP) 它是否完全适合您?
    • @user10626943 - 帖子标记为 data.table,所以我认为 OP 已经在使用 data.table - 如果没有,您需要先转换。已编辑。
    • 对于后来者,.I 是一个等价于seq_len(nrow(x)) 的整数向量。参考:rdrr.io/cran/data.table/man/special-symbols.html(我必须查一下 :-)
    【解决方案3】:

    你也可以做几个滚动连接:

    res = unique(data[, .(GROUP)])
    
    # get row with YEAR above 2000
    res[, w := data[c(.SD, YEAR = 2000), on=.(GROUP, YEAR), roll=-Inf, which=TRUE]]
    
    # if none found, get row with nearest YEAR below   
    res[is.na(w), w := data[c(.SD, YEAR = 2000), on=.(GROUP, YEAR), roll=Inf, which=TRUE]]
    
    # subset by row numbers
    data[res$w]
    
       GROUP YEAR NAME
    1:     3 1985    A
    2:     4 2011    L
    3:     5 2012    G
    4:     6 1994    A
    

    【讨论】:

      猜你喜欢
      • 2016-01-25
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-20
      • 2017-01-18
      • 2021-03-08
      • 1970-01-01
      相关资源
      最近更新 更多