如何有条件地选择每组中的行/行?

时间:2017-06-27 02:44:25

标签: r data.table

示例数据:

tmp_dt <-
    data.table(grp = rep(c(1,2), each = 5), a = 1:10)

# > tmp_dt
#    grp  a
# 1:   1  1
# 2:   1  2
# 3:   1  3
# 4:   1  4
# 5:   1  5
# 6:   2  6
# 7:   2  7
# 8:   2  8
# 9:   2  9
# 10:  2 10

我知道我可以使用.SD

为每个组获取行的子集
tmp_dt[, .SD[c(2,3)], by = grp]
# grp a
# 1:   1 2
# 2:   1 3
# 3:   2 7
# 4:   2 8

我无法工作的是使用grpdata.table有条件地对行进行子集。例如,我希望等效于以下dplyr代码:

tmp_dt %>%
    group_by(grp) %>%
    filter(if_else(grp == 1, row_number() == 3, row_number() == 2)) %>%
    ungroup

# A tibble: 2 × 2
#     grp     a
#     <dbl> <int>
# 1     1     3
# 2     2     7

2 个答案:

答案 0 :(得分:4)

data.table中,您可以执行以下操作:

tmp_dt[tmp_dt[, .I[if(grp == 1) 3 else 2], grp]$V1]

#   grp a
#1:   1 3
#2:   2 7

请注意data.table中的组变量是长度为1的向量(与其他变量不同),因此您可以避免使用效率低于 if {else ifelse

tmp_dt[, length(grp), grp]

#   grp V1
#1:   1  1
#2:   2  1

答案 1 :(得分:4)

对于您的示例,if else方法可能是要走的路。

如果您想延长一点,可以使用“查找”data.table告诉您要使用哪一行

grp_dt <- data.table(grp = c(1,2),
                     row = c(3,2))

tmp_dt[ grp_dt, on = "grp", a[i.row], by = .EACHI]
# tmp_dt[ grp_dt, on = "grp", .(a = a[i.row]), by = .EACHI] ## to keep column name

#    grp V1
# 1:   1  3
# 2:   2  7