簡體   English   中英

R-基於重復序列的子集數據幀

[英]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) )。 使用shiftdata.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM