我有一个数据框
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")
答案 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]