我正在寻找一种方法来分组(或重新思考我如何处理任务)下面的情况留在dplyr而不是“诉诸”data.table我的分析在此块完成之前/之后在dplyr。
情况:给定一个具有多个复制的模拟数据集,我想基于两列密钥(ID和REP)对/ dplyr :: filter进行子集化。
libs <- c("dplyr", "data.table")
lapply(libs, require, character.only = T)
# minimally reproducible example
# dataset
dat <- expand.grid(ID = 1:3, REP = 1:5, TIME = 1:3)
dat <- dat[order(dat$REP, dat$ID, dat$TIME),]
dat$CONC <- runif(nrow(dat), 1, 10)
# key/index
set.seed(1235)
ID_sample <- sample(unique(dat$ID), size = 5, replace = TRUE)
REP_sample <- sample(unique(dat$REP), size = 5, replace = TRUE)
key <- data.frame(ID = ID_sample, REP = REP_sample)
# data table solution
dt <- data.table(dat)
setkey(dt, ID, REP)
dt_subset <- dt[J(key)]
data.table解决方案产生以下结果:
初始数据结构:
ID REP TIME CONC
1 1 1 1 1.310819
2 1 1 2 2.371361
3 1 1 3 7.621165
4 2 1 1 1.010229
5 2 1 2 4.520830
6 2 1 3 5.162452
...
40 2 5 1 6.629885
41 2 5 2 9.680233
42 2 5 3 8.445726
43 3 5 1 3.835254
44 3 5 2 2.917229
45 3 5 3 7.592465
生成密钥和生成的子集:
> key
ID REP
1 1 3
2 2 3
3 1 4
4 3 3
5 3 2
> dt[J(key)]
ID REP TIME CONC
1: 1 3 1 3.038205
2: 1 3 2 5.361020
3: 1 3 3 8.137065
4: 2 3 1 1.053889
5: 2 3 2 2.689412
6: 2 3 3 7.136503
7: 1 4 1 9.137392
8: 1 4 2 6.556821
9: 1 4 3 2.206285
10: 3 3 1 4.330937
11: 3 3 2 4.254630
12: 3 3 3 8.819154
13: 3 2 1 4.508456
14: 3 2 2 7.286893
15: 3 2 3 5.896521
有没有办法在dplyr中使用这个多列索引进行过滤?
到目前为止,我唯一想到的“解决方案”是创建一个新列,如下所示:
dat <- transform(dat, ID_REP = paste0(ID, '_', REP))
KEY <- paste0(ID_sample, '_', REP_sample)
filter(dat, ID_REP %in% KEY)
有效:
ID REP TIME CONC ID_REP
1 3 2 1 4.029622 3_2
2 3 2 2 5.786582 3_2
3 3 2 3 2.846836 3_2
4 1 3 1 4.968823 1_3
5 1 3 2 6.940782 1_3
6 1 3 3 5.017697 1_3
7 2 3 1 7.571442 2_3
8 2 3 2 6.350095 2_3
9 2 3 3 3.924427 2_3
10 3 3 1 6.360991 3_3
11 3 3 2 3.273693 3_3
12 3 3 3 4.029781 3_3
13 1 4 1 6.617855 1_4
14 1 4 2 1.910202 1_4
15 1 4 3 5.496817 1_4
但是不够优雅,并且不提供易于扩展的解决方案。
答案 0 :(得分:5)
您正在寻找semi join:
semi_join(dat, key)
答案 1 :(得分:0)
假设您想要每个键的CONC
变量的总和,
aggregate(CONC~ID+REP+TIME,data=subset(dat,dat$ID %in% key$ID & dat$REP %in% key$REP),sum)
这会给你你想要的吗?