[英]R - Subset dataframe based on a repeated sequence
我試圖基於列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
所以我想根據第v3
列中4 4 2
序列對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中解決這個問題。
我們可以使用data.table
做到這data.table
。 將'data.frame'轉換為'data.table'( setDT(my_df)
)。 使用shift
從data.table
,我們得到下一個元素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"))
只要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
將向量v3變成單個字符串。 然后, grexpr
會在該字符串中找到任何“ 442”子表達式的起始位置。
最后一步使用@ alexis-laz在上面的注釋中建議的outer
函數將data.frame子集化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.