You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 06:57:01