在R

时间:2018-11-22 18:14:43

标签: r delete-row

我有一个数据框

dt <- read.table(text = "
350 16
352 0
354 0
359 0
366 11
376 38  
380 28 
386 0
389 0
397 55 
398 45 
399 0  
400 19  
402 30")

当第二行中连续的行包含零时,我只想保留第二行中非零行之前的零行。

结果必须是:

dt <- read.table(text = "
350 16
359 0
366 11
376 38  
380 28 
389 0
397 55 
398 45 
399 0  
400 19  
402 30")

3 个答案:

答案 0 :(得分:1)

这是一个选项,其中我们根据零值使用rleid创建分组变量,并根据OP帖子中提到的条件使用filter创建分组变量

library(tidyverse)
library(data.table)
dt %>% 
    group_by(grp = rleid(V2 == 0)) %>% 
    filter(all(V2== 0) & row_number()==n() | V2 != 0) %>%
    ungroup %>%
    select(-grp)
# A tibble: 11 x 2
#      V1    V2
#   <int> <int>
# 1   350    16
# 2   359     0
# 3   366    11
# 4   376    38
# 5   380    28
# 6   389     0
# 7   397    55
# 8   398    45
# 9   399     0
#10   400    19
#11   402    30

或者使用data.table,可以应用相同的逻辑

setDT(dt)[dt[, .I[(V2 == 0 & seq_len(.N) == .N) | V2 != 0], rleid(V2 == 0)]$V1]
#     V1 V2
# 1: 350 16
# 2: 359  0
# 3: 366 11
# 4: 376 38
# 5: 380 28
# 6: 389  0
# 7: 397 55
# 8: 398 45
# 9: 399  0
#10: 400 19
#11: 402 30

或者如评论中提到的@jogo一样,用rleid创建一个分组列,然后根据if/else条件对第一行(在'V2'中只有0值)进行子集化< / p>

setDT(dt)[, i:=rleid(V2)][, if (any(V2!=0)) .SD else .SD[.N], i] 

注意:这些是可以概括的灵活解决方案

答案 1 :(得分:1)

简单的一线解决方案:

dplyr::filter(dt, !(V2==0 & lead(V2)==0))

    V1 V2
1  350 16
2  359  0
3  366 11
4  376 38
5  380 28
6  389  0
7  397 55
8  398 45
9  399  0
10 400 19
11 402 30

答案 2 :(得分:0)

这里的data.table等同于@iod的解决方案:

library("data.table")

dt <- fread( 
"350 16
352 0
354 0
359 0
366 11
376 38
380 38
386 0
389 0
397 55
398 45
399 0
400 19
402 30")

dt[V2!=0 | shift(V2, type="lead")!=0]