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

时间:2018-04-11 09:24:40

标签: r conditional subset

我有一些非常大的数据框,我根据某些特定值创建了一个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

在每次70后,我应该再次获得10并重复每个周期。但是,当我在一夜之间在多个文件的循环上设置此过程时,结果包括一些不需要的数据。正如您在上面所看到的,有70到10之间的行。我想消除所有那些在70和10之间的0行。在这个例子中,每个非零值之间只有几行但是我的实际数据还有很多,不仅仅是微不足道的。

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

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

这些数据帧的范围从1到1千万行,所以我不认为设置一个看起来每行和迭代的效果。有什么想法吗?

  

更新

我以为我有一个解决方案,使用的方法与我以前用过的方法相同。

我试过了:

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

我的想法是在每个“坏”之后找到排。在每个“坏”之前和之后10,然后删除使用test2之间的所有位置。它失败了,因为我的数据也有以下情况:

70
0
0
60
0
0
70
10

这里没有配对错误的'考虑到它,如果不是试图去除什么不好,而是使用我的原始方法再次使用我只能找到10-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,]

2 个答案:

答案 0 :(得分: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, ]

答案 1 :(得分:1)

假设您的条件data.frame被称为test

start_end<-data.frame(a=which(test$condition==10),b=which(test$condition==70))

获取标记每个开头和每个结尾的data.frame

获取生成序列的函数

fun.seq<-function(a,b){
  return(seq(a,b,1))
}

在start_end的每一行上运行该函数并取消列表,并选择行

test[unlist(mapply(fun.seq,start_end$a,start_end$b)),]
 [1] 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

我不确定它在数百万行上是否足够快。

也许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