R 仅获取具有给定行数的data.table组
我有以下数据表:R 仅获取具有给定行数的data.table组,r,data.table,R,Data.table,我有以下数据表: 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 = 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
按年份和quar分组,然后设置一列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吗?如果我们需要子集,请使用.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
如果需要子集,请使用.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
当然,这是一个data.table问题,@akrun的回答涵盖了这一点,但为了完成
dplyr解决方案:
图书馆弹琴
dt%>%group_按年,quar%>%filtern==3
一个tibble:9x3
组:年,夸尔[3]
年度夸尔项目
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
基本上:
dt[avedt$item,dt[,cyear,quar],FUN=length==3,]
或
freqt当然这是一个data.table问题,@akrun的回答涵盖了这一问题,但为了完成
dplyr解决方案:
图书馆弹琴
dt%>%group_按年,quar%>%filtern==3
一个tibble:9x3
组:年,夸尔[3]
年度夸尔项目
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
基本上:
dt[avedt$item,dt[,cyear,quar],FUN=length==3,]
或
freqt使用join的另一个选项:
dt[dt[, .N, .(year, quar)][N==3], on=.(year, quar)]
编辑:
为了处理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
)
使用联接的另一个选项:
dt[dt[, .N, .(year, quar)][N==3], on=.(year, quar)]
编辑:
为了处理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
)
@akrun,它和我到目前为止管理的输出是一样的,减去I列。是不是就是项目columnexpectred@akrun,不,整个表减去i。这就是年、季度和项目。@akrun,它与我到目前为止管理的输出是相同的,减去I列。是项目column吗expectred@akrun,不,整个表减去i。这就是年度、季度和项目。是的,就是这样。由于某种原因,我记错了。我给出了每个分组子表中的行。dt[dt[,.I[.N==3],by=cyear,quar][,V1]]这将更通用一些。这部分我的意思是:[,V1]@M-M你可以使用$or[作为默认列名,这是肯定的。我的意思是,如果你想将V1作为参数传递,$V1将不起作用。正如我所说的,这是更通用的,而不是另一个是错误的。是的,就是这样。出于某种原因,我记错了。我给出了每个分组子表中的行。dt[dt[,I][N==3],by=cyear,quar][,V1]]这将是一个更通用的部分。这部分我的意思是:[,V1]@M-M你可以使用$or[作为默认列名,这是肯定的。我的意思是,如果您想将V1作为参数传递,$V1将不起作用。正如我所说,这是更通用的,而不是另一个列名是错误的。与IIs相比,它更快吗?与.I相比,它更快吗