我正在尝试根据列v3
中出现的特定序列对数据框进行子集化。
数据框的示例:
v1 <- c(1:20)
v2 <- c(1,1,0,0,1,0,1,1,1,0,1,1,0,0,0,1,1,0,0,0)
v3 <- c(4,4,2,3,2,3,2,4,4,2,3,2,3,3,3,4,4,2,3,3)
my_df <- data.frame(v1,v2,v3) # creating a dataframe
my_df
v1 v2 v3
1 1 1 4
2 2 1 4
3 3 0 2
4 4 0 3
5 5 1 2
6 6 0 3
7 7 1 2
8 8 1 4
9 9 1 4
10 10 0 2
11 11 1 3
12 12 1 2
13 13 0 3
14 14 0 3
15 15 0 3
16 16 1 4
17 17 1 4
18 18 0 2
19 19 0 3
20 20 0 3
我想要实现的输出应该是这样的
1 1 1 4
2 2 1 4
3 3 0 2
8 8 1 4
9 9 1 4
10 10 0 2
16 16 1 4
17 17 1 4
18 18 0 2
所以我想根据4 4 2
列v3
的顺序对我的df进行子集化。我到目前为止尝试的是:
my_df[which(c(diff(v3))==-2),]
但这仅提取序列4 4 2
的中间四个,如
v1 v2 v3
2 2 1 4
9 9 1 4
17 17 1 4
我尝试的另一种选择:
m = match(v3, c(4,4,2))
> m
[1] 1 1 3 NA 3 NA 3 1 1 3 NA 3 NA NA NA 1 1 3 NA NA
> my_df[!is.na(m),]
v1 v2 v3
1 1 1 4
2 2 1 4
3 3 0 2
5 5 1 2
7 7 1 2
8 8 1 4
9 9 1 4
10 10 0 2
12 12 1 2
16 16 1 4
17 17 1 4
18 18 0 2
这个输出给了我所有4和2但不是我想要的序列4 4 2
。任何帮助,将不胜感激。
我已经在matlab中用for和if循环实现了这个,但我只是想知道如何以无循环的方式在R中解决这个问题。
答案 0 :(得分:1)
我们可以使用data.table
执行此操作。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(my_df)
)。使用shift
中的data.table
,我们获得了type = "lead"
的下一个元素。由于shift
采用n
的向量,我们指定n = 0:2
,因此我们得到三列,其中n = 0
对应于原始的&#39; v3&#39}。列和其他第1和第2个下一个值。然后,paste
元素rowwise(do.call(paste0, ...
),检查它是否等于442,获取TRUE值的索引(which
),使用rep
复制索引并添加0:2,以便我们获得每个索引的三行索引。这可用于对原始数据集行进行子集化。
library(data.table)
setDT(my_df)[my_df[, rep(which(do.call(paste0, shift(v3, 0:2,
type= "lead")) == 442), each = 3) + 0:2]]
# v1 v2 v3
#1: 1 1 4
#2: 2 1 4
#3: 3 0 2
#4: 8 1 4
#5: 9 1 4
#6: 10 0 2
#7: 16 1 4
#8: 17 1 4
#9: 18 0 2
my_df <- structure(list(v1 = 1:20, v2 = c(1L, 1L, 0L, 0L, 1L, 0L, 1L,
1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 0L, 0L), v3 = c(4L,
4L, 2L, 3L, 2L, 3L, 2L, 4L, 4L, 2L, 3L, 2L, 3L, 3L, 3L, 4L, 4L,
2L, 3L, 3L)), .Names = c("v1", "v2", "v3"), class = "data.frame",
row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
"14", "15", "16", "17", "18", "19", "20"))
答案 1 :(得分:1)
只要v3没有任何缺失值且v3的值是单个字符,您也可以使用gregexpr
完成此操作,如下所示
# get the row indices where the pattern 442 starts c(1 , 8, 16)
rowstarts <- unlist(gregexpr("442", paste(my_df$v3, collapse="")))
# extract rows from the data fram
dfNew <- my_df[sort(c(outer(rowstarts, (0:2), "+"))), ]
返回
dfNew
v1 v2 v3
1 1 1 4
2 2 1 4
3 3 0 2
8 8 1 4
9 9 1 4
10 10 0 2
16 16 1 4
17 17 1 4
18 18 0 2
带有collapse参数的 paste
将向量v3转换为单个字符串。 grexpr
然后在此字符串中找到任何“442”子表达式的起始位置。
最后一步使用@ alexis-laz在上面评论中建议的outer
函数对data.frame进行子集化。