R语言 只获取给定行数的数据表组[重复]

hpcdzsge  于 2023-04-03  发布在  其他
关注(0)|答案(3)|浏览(138)

此问题在此处已有答案

Subset data frame based on number of rows per group(4个答案)
三年前关闭了。
我有以下数据.表:

dt = data.table(year=c(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2),
                quar=c(1, 1, 1, 2, 2, 3, 4, 4, 4, 1, 1, 1),
                item=c(1, 2, 3, 1, 2, 1, 1, 2, 3, 1, 2, 3))

某些期间(按年和季度定义)有三个项目:

  • Y1Q1、Y1Q4、Y2Q1

其他时期则不会:

  • Y1Q2有2个项目
  • Y1Q3有1项

我如何才能只得到包含所有三个项目的行?
目前为止我所做的

dt[dt[, "i" := nrow(.SD) == 3, .(year, quar)]$i]
> year | quar | item | i
> -----+------+------+-----
> 1    | 1    | 1    | TRUE
> 1    | 1    | 2    | TRUE
> 1    | 1    | 3    | TRUE
> 1    | 4    | 1    | TRUE
> 1    | 4    | 2    | TRUE
> 1    | 4    | 3    | TRUE
> 2    | 1    | 1    | TRUE
> 2    | 1    | 2    | TRUE
> 2    | 1    | 3    | TRUE

它按yearquar分组,然后设置一个列i,该列说明该组是否有效。该组中的所有行都获得i的计算值。
但是,它的副作用是向表中添加了一个真实的的i列。
我尝试使用一个用.(i =...)声明的临时列,但是i列的长度与较短的分组表的长度相同,于是我们得到

dt[dt[, .(i = nrow(.SD) == 3), .(year, quar)]$i]
> Error in `[.data.table`(dt, dt[, .(i = nrow(.SD) == 3), .(year, quar)]$i) :
> i evaluates to a logical vector length 5 but there are 12 rows. [...]

那么,有没有更优雅的方法来解决这个问题呢?或者我应该只使用这个,然后删除i

mkh04yzy

mkh04yzy1#

如果我们需要子集,使用.I来获取行索引和子集

dt[dt[, .I[.N == 3], .(year, quar)]$V1]
#    year quar item
#1:    1    1    1
#2:    1    1    2
#3:    1    1    3
#4:    1    4    1
#5:    1    4    2
#6:    1    4    3
#7:    2    1    1
#8:    2    1    2
#9:    2    1    3

或者使用.SD,但可能会很慢

dt[, .SD[.N == 3], .(year, quar)]

或者另一个选项是if/else

dt[, if(.N == 3) .SD, .(year, quar)]
lskq00tm

lskq00tm2#

使用join的另一个选项:

dt[dt[, .N, .(year, quar)][N==3], on=.(year, quar)]

edit:为了解决akrun注解,速度确实取决于数据集的特征。以下是示例数据集的计时:

set.seed(0L)
ngrp <- 1e6
x <- sample(1:3, ngrp, TRUE)
dt <- data.table(year=rep(1:ngrp, times=x))[,
    quar:=year]

microbenchmark::microbenchmark(
    mtd0=dt[dt[, .I[.N == 3], .(year, quar)]$V1],
    mtd1=dt[dt[, .N, .(year, quar)][N==3], on=.(year, quar)],
    times=3L
)

计时:

Unit: milliseconds
 expr      min       lq     mean   median       uq      max neval cld
 mtd0 851.4689 878.5954 891.4074 905.7219 911.3766 917.0314     3   b
 mtd1 268.4806 295.0696 317.0266 321.6586 341.2996 360.9407     3  a
wh6knrhe

wh6knrhe3#

当然,这是一个data.table问题,@akrun的答案涵盖了它,但为了完成;
dplyr解决方案:

library(dplyr)
dt %>% group_by(year,quar) %>% filter(n()==3)

## A tibble: 9 x 3
## Groups:   year, quar [3]
#   year  quar  item
#  <dbl> <dbl> <dbl>
#1     1     1     1
#2     1     1     2
#3     1     1     3
#4     1     4     1
#5     1     4     2
#6     1     4     3
#7     2     1     1
#8     2     1     2
#9     2     1     3

Base中:

dt[ave(dt$item, dt[,c("year","quar")], FUN = length) == 3, ]

freqt <- as.data.frame(table(dt[,c("year", "quar")]))
subt <- freqt[freqt$Freq == 3,c("year", "quar")]

merge(x = subt, y = dt, by = c("year", "quar") , all.x = TRUE)

相关问题