【问题标题】:R - Subset dataframe based on a repeated sequenceR - 基于重复序列的子集数据帧
【发布时间】:2016-08-29 17:05:06
【问题描述】:

我正在尝试根据列 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 2v3 中的序列对我的df 进行子集化。到目前为止我尝试的是:

my_df[which(c(diff(v3))==-2),]

但这只会提取序列4 4 2like的中间四个

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 中以无循环的方式解决这个问题。

【问题讨论】:

  • 参见here 一个关于在数字向量中查找序列的类似问题。那里的所有答案都会输出一个匹配发生位置的索引向量(此处为c(1, 8, 16)),您可以使用它来对您的my_df 进行子集化。 IE。假设i = c(1, 8, 16),那么c(outer(0:2, i, "+")) 给出所有索引

标签: r sequence subset


【解决方案1】:

我们可以通过data.table 做到这一点。将“data.frame”转换为“data.table”(setDT(my_df))。使用来自data.tableshift,我们得到带有type = "lead" 的下一个元素。由于shift 采用n 的向量,我们指定n = 0:2,因此我们得到三列,其中n = 0 对应于原始'v3' 列和其他第一个和第二个下一个值。然后,paste 元素按行排列(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"))

【讨论】:

  • 一个问题,现在将您的技术应用于输出序列,我正在尝试计算 v2 中的 110 和 111。 which(do.call(paste0, shift(seq$v2, 0:2, type= "lead")) == 110) [1] 7 所以我知道只有一个 110 序列,但它对于 111 which(do.call(paste0, shift(seq$v2, 0:2, type= "lead")) == 111) [1] 1 2 3 4 5 6 的工作方式不同,它提供了所有索引。更新 v2 v2 &lt;- c(1,1,1,0,1,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0)
  • @Amgh 你的例子没有 111。
  • 是的,我更新了 v2 以便进一步分析v1 &lt;- c(1:20) &gt; v2 &lt;- c(1,1,1,0,1,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0) &gt; v3 &lt;- c(4,4,2,3,2,3,2,4,4,2,3,2,3,3,3,4,4,2,3,3) &gt; my_df &lt;- data.frame(v1,v2,v3) # creating a datafram
  • @Amgh 我得到setDT(my_df)[, which(do.call(paste0, shift(v3, 0:2, type= "lead")) == 111)] #integer(0)
  • 我们得到了这个更新后的数据帧的输出,比如seq &lt;- setDT(my_df)[my_df[, rep(which(do.call(paste0, shift(v3, 0:2, type= "lead")) == 442), each = 3) + 0:2]],现在我确实应用了which(do.call(paste0, shift(seq$v2, 0:2, type= "lead")) == 111),输出是'[1] 1 2 3 4 5 6',但是如果我这样做which(do.call(paste0, shift(seq$v2, 0:2, type= "lead")) == 110) 然后输出是[1] 7
【解决方案2】:

只要 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

paste 使用 collapse 参数将向量 v3 转换为单个字符串。 grexpr 然后在此字符串中查找任何“442”子表达式的起始位置。

最后一步使用上面 cmets 中 @alexis-laz 建议的 outer 函数对 data.frame 进行子集化。

【讨论】:

    猜你喜欢
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 2014-10-30
    • 2017-04-06
    • 2016-03-12
    相关资源
    最近更新 更多