R根据条件删除行(高级)

R根据条件删除行(高级),r,conditional,subset,R,Conditional,Subset,我有一些非常大的数据帧,我创建了一个条件列,根据一些特定的值可以是10、1、60或70。两者之间的所有值均为0。然后,我创建了一个小数据帧,每个位置为10和70(我想要的每个序列的开始和结束),并设法对我的数据帧进行子集,这样我只剩下10和70之间的数据帧(包括它们之间的1、60和0) 生成的数据帧几乎就是我需要的子集,条件列现在看起来如下所示: condition 10 0 0 1

我有一些非常大的数据帧,我创建了一个条件列,根据一些特定的值可以是10、1、60或70。两者之间的所有值均为0。然后,我创建了一个小数据帧,每个位置为10和70(我想要的每个序列的开始和结束),并设法对我的数据帧进行子集,这样我只剩下10和70之间的数据帧(包括它们之间的1、60和0)

生成的数据帧几乎就是我需要的子集,条件列现在看起来如下所示:

    condition
           10
            0
            0
            1
            0
            0
            0
            60
            0
            0
            70
            10
            0
            0
            1
            0
            60
            0
            0
            70
            0
            0
            10
            0
            0
            1
            0
            0
            60
            0
            0
            70
            0
            10
            0
            0
            1
            0
            0
            0
            0
            60
            0
            0
            0
            70
df2 = df[df$ff == 10 | df$ff == 70,]
test = data.frame(s = df2$datetime[c(T,F)], e =  df2$datetime[c(F,T)])
for(i in 1:length(test$s)){test$ss[i] = which(df$datetime == test$s[i])}
for(i in 1:length(test$s)){test$ee[i] = which(df$datetime == test$e[i])}
for(i in 1:length(test$s)){df$t[test$ss[i]:test$ee[i]] = 1}
df_all= df[df$t ==1,]
在每70次之后,我应该再次得到10次,并重复每个周期。然而,当我一夜之间在多个文件的循环中设置此过程时,结果包括一些不需要的数据。正如您在上面看到的,在70和10之间有行。我想消除所有那些0在70和10之间的行。在本例中,每个非零值之间只有几行,但我的实际数据有更多的行,因此它不是微不足道的

因此,从上面得到的数据帧将是:

condition
       10
        0
        0
        1
        0
        0
        0
        60
        0
        0
        70
        10
        0
        0
        1
        0
        60
        0
        0
        70
        10
        0
        0
        1
        0
        0
        60
        0
        0
        70
        10
        0
        0
        1
        0
        0
        0
        0
        60
        0
        0
        0
        70
这些数据帧的范围从100万行到1000万行,所以我认为设置一个查看每一行并进行迭代的外观是没有效率的。有什么想法吗

更新

我想我已经有了一个解决方案,使用的方法和我在这里使用的方法相同

我试过:

test$t = NA
test$t = ifelse(shift(test$ff== 70) & test$ff != 10, 1, test$t)
test$t = ifelse(shift(test$ff== 10, type = "lead") & test$ff != 70, 1, test$t)
test2 = data.frame(s = test$t[c(T,F)], e =  test$t[c(F,T)])
Error in data.frame(s = test$t[c(T, F)], e = test$t[c(F, T)]) : 
  arguments imply differing number of rows: 44085, 44084
我的想法是在每个'bad'70之后和每个'bad'10之前找到行,然后使用test2删除所有位置。它失败了,因为我的数据还包含以下情况:

70
0
0
60
0
0
70
10
这里没有70的配对“坏”10。想一想,如果我不再尝试删除不好的部分,而是再次使用我原来只查找10-70序列的方法进行子集,我可能会解决它。我这样做的方式如下:

    condition
           10
            0
            0
            1
            0
            0
            0
            60
            0
            0
            70
            10
            0
            0
            1
            0
            60
            0
            0
            70
            0
            0
            10
            0
            0
            1
            0
            0
            60
            0
            0
            70
            0
            10
            0
            0
            1
            0
            0
            0
            0
            60
            0
            0
            0
            70
df2 = df[df$ff == 10 | df$ff == 70,]
test = data.frame(s = df2$datetime[c(T,F)], e =  df2$datetime[c(F,T)])
for(i in 1:length(test$s)){test$ss[i] = which(df$datetime == test$s[i])}
for(i in 1:length(test$s)){test$ee[i] = which(df$datetime == test$e[i])}
for(i in 1:length(test$s)){df$t[test$ss[i]:test$ee[i]] = 1}
df_all= df[df$t ==1,]
先进的,嗯

zoo::na.locf
这里是你的朋友:

condition <- as.numeric(c("10", "0", "0", "1", "0", "0", "0", "60", 
      "0", "0", "70", "10", "0", "0", "1", "0", "60", "0", "0", "70",
      "0", "0", "10"))

dfr <- data.frame(condition = condition)

dfr$between <- NA
dfr$between[dfr$condition == 70] <- TRUE
dfr$between[dfr$condition == 10] <- FALSE
dfr$between <- zoo::na.locf(dfr$between, na.rm = FALSE)
dfr$between[dfr$condition == 70] <- FALSE # don't remove the 70s themselves

dfr[! dfr$between, ]

condition假设您的condition data.frame被称为
test

start_end<-data.frame(a=which(test$condition==10),b=which(test$condition==70))
我不确定它在数百万行上是否足够快

也许data.table能够以更快的方式完成这项工作,但我不确定如何完成

我想出了一个非常俗气的方法,很简单,但很有效

mapply的输出:

    mapply(fun.seq,start_end$a,start_end$b)
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10 11

[[2]]
[1] 12 13 14 15 16 17 18 19 20

[[3]]
 [1] 23 24 25 26 27 28 29 30 31 32

[[4]]
 [1] 34 35 36 37 38 39 40 41 42 43 44 45 46

我认为问题与此类似:为了澄清问题,您的目标是识别并删除最上面示例中存在于值为70,10的行之间的所有行?也就是说,在上面的例子中,你有70,0,0,10,你想删除两个0,0行,只得到70,10?是的,虽然我想我可以使用类似的解决方案来获得这些子集,但遇到了另一个问题,将使用
立即更新(df$datetime==test$s[I])
在循环中是个问题,因为循环中的日期时间似乎不起作用。重新运行我的原始代码修复了它。但是我学的工具越多越好,谢谢!