在具有Data.Table的组中有条件地选择行

时间:2018-11-12 04:16:35

标签: r data.table

我正在寻找使用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)

Data.table:

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

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

3 个答案:

答案 0 :(得分:5)

如果您将特殊的data.table行计数器作为子集,则

.I应该简单得多:

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

因此,我在这里要做的就是为每个data级别上的每个计算获取整个by=的匹配行索引。然后,使用这些行索引再次子集data

答案 1 :(得分: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

答案 2 :(得分:2)

使用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

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