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

dplyr中基于当前Year变量的条件判断失效问题求助

dplyr动态标记"断点"行的问题解决

示例数据集

df <- tibble::tribble(
  ~INSTRUMENT_USED, ~Year, ~UniqueCount,
  "QUEST_A", 2015, 1,
  "QUEST_A", 2016, 1,
  "QUEST_A", 2017, 1,
  "QUEST_A", 2018, 1,
  "QUEST_A", 2019, 1,
  "QUEST_A", 2020, 1,
  "QUEST_A", 2021, 0,
  "QUEST_A", 2022, 0,
  "QUEST_A", 2023, 0,
  "QUEST_B", 2015, 1,
  "QUEST_B", 2016, 1,
  "QUEST_B", 2017, 1,
  "QUEST_B", 2018, 1,
  "QUEST_B", 2019, 0,
  "QUEST_B", 2020, 0,
  "QUEST_B", 2021, 1,
  "QUEST_B", 2022, 0,
  "QUEST_B", 2023, 0
)

需求说明

生成dbreak变量,仅当某一行同时满足以下条件时标记为Yes,其余为No:

  • 该行之前所有年份的UniqueCount均为1
  • 该行之后所有年份的UniqueCount均为0

示例中仅QUEST_A 2021行符合要求。

错误代码问题分析

你手动硬编码年份时结果正确,但替换为动态Year变量后失效,核心问题是**mutate中直接使用Year向量进行筛选时,是组内向量的逐元素比较,而非针对当前行的单个年份值**:

看错误代码中的条件:

all(UniqueCount[Year <= Year-1] == 1)

这里的Year是整个分组的年份向量,Year <= Year-1会生成一组逻辑值(比如2015<=2014为FALSE,2016<=2015为FALSE...),完全不是你想要的"当前行年份之前的所有年份"。

而all(UniqueCount[Year > Year] ==0)这个条件永远为TRUE,因为Year > Year对所有元素都是FALSE,空向量的all()默认返回TRUE,导致不符合条件的行被错误标记。

正确实现方案

方法1:用累积函数预处理状态(高效简洁)

df <- df %>%
  group_by(INSTRUMENT_USED) %>%
  arrange(INSTRUMENT_USED, Year) %>%
  mutate(
    # 检查当前行及之前是否从未出现过非1值
    all_prev_one = cumsum(UniqueCount != 1) == 0,
    # 检查当前行及之后是否从未出现过非0值(反向累积)
    all_next_zero = rev(cumsum(rev(UniqueCount) != 0)) == 0,
    # 组合所有条件:当前是0、前一行是1、前后状态都符合
    dbreak = ifelse(UniqueCount == 0 & lag(UniqueCount) == 1 & all_prev_one & all_next_zero, 
                    "Yes", "No")
  ) %>%
  ungroup()

方法2:逐行判断(直观易懂)

如果更习惯逐行处理逻辑,可以用purrr::pmap:

library(purrr)

df <- df %>%
  group_by(INSTRUMENT_USED) %>%
  arrange(INSTRUMENT_USED, Year) %>%
  mutate(
    dbreak = pmap_chr(list(Year, UniqueCount, lag(UniqueCount)), 
                      function(current_year, current_uc, prev_uc) {
                        # 先排除不满足基础条件的行
                        if (current_uc != 0 || prev_uc != 1) return("No")
                        # 再检查前后所有年份的状态
                        if (all(UniqueCount[Year < current_year] == 1) && all(UniqueCount[Year > current_year] == 0)) {
                          "Yes"
                        } else {
                          "No"
                        }
                      })
  ) %>%
  ungroup()

运行上述任意代码后,QUEST_A 2021的dbreak会被标记为Yes,其余行均为No,符合预期。

内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:52:07