根据行中的字符序列对数据进行子集

时间:2018-08-17 17:46:14

标签: r

如何通过连续的字符行模式对df进行子集设置?在下面的示例中,我想连续地对具有历史值“ TRUE”,“ FALSE”,“ TRUE”的数据进行子集化。下面的数据有点奇怪,但是您知道了!

value <- c(1/1/16,1/2/16, 1/3/16, 1/4/16, 1/5/16, 1/6/16, 1/7/16, 1/8/16, 1/9/16, 1/10/16)

history <- c("TRUE", "FALSE", "TRUE", "TRUE", "FALSE", "TRUE", "TRUE", "TRUE", "FALSE", "TRUE")

df <- data.frame(value, history)
df

         value history  
1  0.062500000    TRUE  
2  0.031250000   FALSE  
3  0.020833333    TRUE  
4  0.015625000    TRUE  
5  0.012500000   FALSE  
6  0.010416667    TRUE  
7  0.008928571    TRUE  
8  0.007812500    TRUE  
9  0.006944444   FALSE  
10 0.006250000    TRUE  

我已经尝试过grepl,但是它适用于字符串-不适用于连续跨行的字符序列。

输出将与上面相同,但没有第7行,因为它不遵循上述模式。

3 个答案:

答案 0 :(得分:1)

你可以做...

s = c("TRUE", "FALSE", "TRUE")

library(data.table)
w = as.data.table(embed(history, length(s)))[as.list(s), on=paste0("V", seq_along(s)), which=TRUE]

df$v <- FALSE
df$v[w + rep(seq_along(s)-1L, each=length(s))] <- TRUE

         value history     v
1  0.062500000    TRUE  TRUE
2  0.031250000   FALSE  TRUE
3  0.020833333    TRUE  TRUE
4  0.015625000    TRUE  TRUE
5  0.012500000   FALSE  TRUE
6  0.010416667    TRUE  TRUE
7  0.008928571    TRUE FALSE
8  0.007812500    TRUE  TRUE
9  0.006944444   FALSE  TRUE
10 0.006250000    TRUE  TRUE

然后您可以像subset(df, v == TRUE)一样进行过滤。


使用data.table联接,x[i, which=TRUE]i = as.list(s)中查找x = embed(history, length(s))并报告x的哪些行被匹配的情况:

> as.data.table(as.list(s))
     V1    V2   V3
1: TRUE FALSE TRUE

> as.data.table(embed(history, length(s)))
      V1    V2    V3
1:  TRUE FALSE  TRUE
2:  TRUE  TRUE FALSE
3: FALSE  TRUE  TRUE
4:  TRUE FALSE  TRUE
5:  TRUE  TRUE FALSE
6:  TRUE  TRUE  TRUE
7: FALSE  TRUE  TRUE
8:  TRUE FALSE  TRUE

w + rep(...)与@GGrothendieck的outer(...)相同,除了这里w包含比赛开始位置,而不是比赛结束位置。

答案 1 :(得分:1)

问题中的数据看起来很奇怪,因此我们在末尾使用了注释中的数据。如果您确实有一个字符向量或因子,其值分别为“ TRUE”和“ FALSE”,则可以使用以下命令将其轻松转换为逻辑:

df <- transform(df, history = history == "TRUE")

1)滚动应用:首先定义图案,然后使用带有rollapplyr的移动窗口进行搜索。如果这是模式匹配的结尾,则给出的逻辑向量为TRUE。查找TRUE的索引,并包括前面的两个索引。最后执行子集。

library(zoo)

pattern <- c(TRUE, FALSE, TRUE)
ix <- which(rollapplyr(df$history, length(pattern), identical, pattern, fill = FALSE))
ix <- unique(sort(c(outer(ix, seq_along(pattern) - 1L, "-"))))
df[ix, ]

给予:

         value history
1  0.062500000    TRUE
2  0.031250000   FALSE
3  0.020833333    TRUE
4  0.015625000    TRUE
5  0.012500000   FALSE
6  0.010416667    TRUE
8  0.007812500    TRUE
9  0.006944444   FALSE
10 0.006250000    TRUE

1a)magrittr (1)中的此代码可以使用magrittr表示。 (解决方案(2)也可以使用magrittr遵循类似的思想表示。)

library(magrittr)
library(zoo)

df %>%
  extract(
   extract(.,, "history") %>%
   rollapplyr(length(pattern), identical, pattern, fill = FALSE) %>%
   which %>%
   outer(seq_along(pattern) - 1L, "-") %>%
   sort %>%
   unique, )

2)gregexpr 使用上面定义的pattern,我们将其转换为0和1的字符串,还将df $ history转换为这样的字符串。然后,我们可以使用gregexpr查找每个匹配项的第一个元素的索引,然后将其扩展到所有索引和子集。我们得到与以前相同的答案。此替代方法不使用任何软件包。

collapse <- function(x) paste0(x + 0, collapse = "")
ix <- gregexpr(collapse(pattern), collapse(df$history))[[1]]
ix <- unique(sort(c(outer(ix, seq_along(pattern) - 1L, "+"))))
df[ix, ]

注意

Lines <- "
         value history  
1  0.062500000    TRUE  
2  0.031250000   FALSE  
3  0.020833333    TRUE  
4  0.015625000    TRUE  
5  0.012500000   FALSE  
6  0.010416667    TRUE  
7  0.008928571    TRUE  
8  0.007812500    TRUE  
9  0.006944444   FALSE  
10 0.006250000    TRUE"
df <- read.table(text = Lines)

答案 2 :(得分:0)

使用滞后的选项:

    df <- data.frame(value, history)

    n<- grepl("TRUE, FALSE, TRUE", paste(lag(lag(history)), (lag(history)), history, sep = ", "))[-(1:2)]

    cond <- n |lag(n)|lag(lag(n)) 
    cond <- c(cond, cond[length(history)-2], cond[length(history)-2])
    df[cond, ]