R语言按分组选取每段零值前最后一个非零值对应行的实现问题
问题描述
现有如下数据框:
variable Date values values2 1 a 2017-01-01 3 1 2 a 2017-01-02 4 2 3 a 2017-01-03 5 1 # non-zero followed by zero 4 a 2017-01-04 0 2 5 a 2017-01-05 0 2 6 a 2017-01-06 0 3 7 b 2017-01-01 10 1 8 b 2017-01-02 11 2 9 b 2017-01-03 12 2 10 b 2017-01-04 13 3 11 b 2017-01-05 14 0 12 b 2017-01-06 15 1 13 c 2017-01-01 45 2 14 c 2017-01-02 50 3 # non-zero followed by zero 15 c 2017-01-03 0 0 16 c 2017-01-04 0 2 17 c 2017-01-05 10 1 # non-zero followed by zero 18 c 2017-01-06 0 1
需要筛选出values列中非零值后紧跟零值的行,预期输出如下:
1 a 2017-01-03 5 1 2 c 2017-01-02 50 3 3 c 2017-01-05 10 1
注意:同一个variable分组内可能存在多个符合要求的行。
现有代码仅能返回每个分组的最后一个符合条件的元素,无法得到正确结果,代码和实际输出如下:
test_df <- structure(list(variable = c("a", "a", "a", "a", "a", "a", "b", "b", "b", "b", "b", "b", "c", "c", "c", "c", "c","c"), Date = structure(c(17167, 17168, 17169, 17170, 17171, 17172, 17167, 17168, 17169, 17170, 17171, 17172, 17167, 17168, 17169, 17170, 17171, 17172), class = "Date"), values = c(3, 4, 5, 0, 0, 0, 10, 11, 12, 13, 14, 15, 45, 50,0, 0, 10, 0), values2 = c(1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 0, 1, 2, 3, 0, 2, 1, 1)), row.names = c(NA, -18L), class = "data.frame", .Names = c("variable", "Date", "values", "values2")) test_df %>% group_by(variable=factor(variable)) %>% filter(any(values==0)) %>% filter(values != 0) %>% arrange(Date) %>% slice(n()) %>% ungroup() # 实际输出 1 a 2017-01-03 5 1 2 c 2017-01-05 10 1
解决方案
原代码问题出在slice(n())语句,只会保留每个分组的最后一行非零值,自然会漏掉同分组内多个符合条件的行。你可以用lead()函数取当前行的下一行值做判断,修改后代码如下:
library(dplyr) test_df %>% group_by(variable) %>% # 分组内按日期排序,保证行顺序为时间先后 arrange(Date, .by_group = TRUE) %>% # 筛选条件:当前值非0,下一行值为0 filter(values != 0, lead(values) == 0) %>% ungroup()
运行后输出结果和预期完全一致:
# A tibble: 3 × 4 variable Date values values2 <chr> <date> <dbl> <dbl> 1 a 2017-01-03 5 1 2 c 2017-01-02 50 3 3 c 2017-01-05 10 1
内容的提问来源于stack exchange,提问作者Zizou
相关产品推荐
相关产品推荐

