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

如何判断Type为New的A年ID是否存在于A+1和A+3年份?

问题解决:判断新生ID在后续年份的存在性

问题描述

我有一个包含ID、ANNO(年份)、COD_CARRERA(专业ID)、TIPO_ALU(学生类型,取值为"NUEVO"或"old")、ANNO_RET_1(入学后第1年)、ANNO_RET_3(入学后第3年)的DataFrame,需要为TIPO_ALU="NUEVO"的ID新增两列:

  • 判断该ID是否存在于ANNO_RET_1对应的年份数据中
  • 判断该ID是否存在于ANNO_RET_3对应的年份数据中

我之前尝试编写了检查存在性的函数:

check_presence_1 <- function(BBDD2, ANNO) {
  BBDD2 %>%
    select(ID) %>%
    filter(ANNO == ANNO_RET_1) %>%
    mutate(present = TRUE)
}

(类似地写了check_presence_3函数),随后用以下代码新增列,但得到无意义的结果:

result_data <- BBDD2 %>%
  filter(TIPO_ALU == "NUEVO") %>%
  mutate(first_year = min(ANNO), 
    present_x1 = ifelse(ID %in% check_presence_1(filter(., ANNO > first_year), ANNO_RET_1)$ID, TRUE, FALSE),
    present_x3 = ifelse(ID %in% check_presence_3(filter(., ANNO > first_year), ANNO_RET_3)$ID, TRUE, FALSE))

我很久没使用R,寻求正确解决方案。

附数据样本:

structure(list(ANNO = c(2012, 2012, 2012, 2012, 2012), ID = c(14L, 
37L, 76L, 100L, 112L), TIPO_ALU = c("NUEVO", "NUEVO", "NUEVO", 
"NUEVO", "NUEVO"), COD_CARRERA = c("I70S1C751J1V1", "I70S1C756J2V1", 
"I70S1C603J1V1", "I70S1C779J2V1", "I70S1C611J1V1"), ANNO_RET_1 = c(2013, 
2013, 2013, 2013, 2013), ANNO_RET_3 = c(2015, 2015, 2015, 2015, 
2015)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"
))

期望新增列示例:PRESENT_ANNO+1 = c(1, 1, 0, 1, 0),PRESENT_ANNO+3 = c(0, 1, 0, 0, 0)


问题分析

原代码的核心问题:

  • 函数中filter(ANNO == ANNO_RET_1)存在变量名冲突,函数参数ANNO与数据列ANNO重名,导致筛选逻辑完全错误
  • mutate中first_year = min(ANNO)取的是整个筛选后数据集的最小年份,而非每个ID对应的入学年份,逻辑不符合需求
  • 调用检查函数时的参数传递逻辑混乱,没有正确关联每个ID对应的ANNO_RET_1/ANNO_RET_3年份

正确解决方案

方法一:预先生成年份-ID映射表(高效版)

先整理出每个年份下存在的ID集合,再对新生数据做匹配,适合大数据量场景:

library(dplyr)

# 1. 生成年份-ID映射表:存储每个年份对应的所有ID
year_id_map <- BBDD2 %>%
  group_by(ANNO) %>%
  summarise(existing_ids = list(ID), .groups = "drop")

# 2. 处理新生数据,新增存在性列
result_data <- BBDD2 %>%
  filter(TIPO_ALU == "NUEVO") %>%
  # 匹配入学后第1年的ID集合
  left_join(year_id_map, by = c("ANNO_RET_1" = "ANNO")) %>%
  mutate(PRESENT_ANNO_plus_1 = as.integer(ID %in% unlist(existing_ids))) %>%
  select(-existing_ids) %>%
  # 匹配入学后第3年的ID集合
  left_join(year_id_map, by = c("ANNO_RET_3" = "ANNO")) %>%
  mutate(PRESENT_ANNO_plus_3 = as.integer(ID %in% unlist(existing_ids))) %>%
  select(-existing_ids)

代码说明

  • year_id_map:通过group_by+summarise生成每个年份对应的ID列表,后续可快速查找
  • left_join:将新生的ANNO_RET_1/ANNO_RET_3与映射表关联,获取目标年份的所有ID
  • as.integer(...):将逻辑判断结果转为0/1数值,匹配期望的输出格式

方法二:逐行直接检查(简洁版)

如果数据量不大,可直接用rowwise()逐行验证,代码更简洁:

library(dplyr)

result_data <- BBDD2 %>%
  filter(TIPO_ALU == "NUEVO") %>%
  rowwise() %>%
  mutate(
    PRESENT_ANNO_plus_1 = as.integer(any(BBDD2$ANNO == ANNO_RET_1 & BBDD2$ID == ID)),
    PRESENT_ANNO_plus_3 = as.integer(any(BBDD2$ANNO == ANNO_RET_3 & BBDD2$ID == ID))
  ) %>%
  ungroup()

代码说明

  • rowwise():让后续的mutate逐行处理每个ID
  • any(...):直接检查当前ID是否在目标年份的数据集里,返回逻辑值后转为0/1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:42:49