我有一个表格中的数据:
id source
1 m
1 p
1 l1
1 l1
2 t
2 q
3 p
3 l1
3 n
3 l1
现在对于每个 id,我想在源中出现 l1 时识别它,并在 l1 之前提取观察结果。例如:对于 id 1,l1 中的第三个源和之前的观察是 p。所以我的数据应该是这样的:
id source
1 p
3 p
3 n
我如何在 R 中创建它?
我有一个表格中的数据:
id source
1 m
1 p
1 l1
1 l1
2 t
2 q
3 p
3 l1
3 n
3 l1
现在对于每个 id,我想在源中出现 l1 时识别它,并在 l1 之前提取观察结果。例如:对于 id 1,l1 中的第三个源和之前的观察是 p。所以我的数据应该是这样的:
id source
1 p
3 p
3 n
我如何在 R 中创建它?
数据表解决方案
library(data.table)
dd <- data.table(df)
dd[, source[match('l1', source)-1L],by = id]
这是另一个 data.table 解决方案。我无法从@mnel 的早期版本中获得看似正确的答案。
library(data.table)
## Create the test data table:
dt <- data.table(id=c(1,1,1,1,2,2,3,3,3,3),
source1=c("m","p","l1","l1","t","q","p","l1","n","l1"))
dt[,list(id, source1, source0=c(NA,source1[seq_len(.N-1L)]))][source1=="l1"]
## id source1 source0
## 1: 1 l1 p
## 2: 1 l1 l1
## 3: 3 l1 p
## 4: 3 l1 n
这是将列 source0 添加到获取前一行(或第一行的 NA)的数据表中。这.N
是一个行号,我seq_len
用来获取前一个行号。然后它对原始 source1 的值为“l1”的结果进行子集化。
可能有更直接的方法,但试试这个:
#get your data
test <- read.table(text="id source
1 m
1 p
1 l1
1 l1
2 t
2 q
3 p
3 l1
3 n
3 l1",header=TRUE)
# do some picking of the cases
result <- do.call(rbind,by(test,test$id,function(x) x[which(x$source=="l1")-1,]))
result <- result[result$source!="l1",]
这使:
> result
id source
2 1 p
7 3 p
9 3 n
这是一个矢量化解决方案,仅使用来自 R 基础的简单函数。
如果DF
是输入数据框,那么sel
是一个逻辑向量,其TRUE
组件选择所需的行。&
由符号连接的三个术语选择这些行:
source
列等于“l1”和l1
并且id
的长度sel
比 in 的行数少一,DF
因此我们使用它which
来避免回收sel
.
is.l1 <- DF$source == "l1"
sel <- is.l1[-1] & !is.l1[-nrow(DF)] & duplicated(DF$id)[-1]
DF[which(sel),]
最后一行的结果是:
id source
2 1 p
7 3 p
9 3 n