如何用R语言dplyr包创建事件前条件虚拟变量?
问题分析与解决方案
首先,先说说你代码里的问题:
ifelse语法错误:ifelse()函数必须传入三个参数:判断条件、条件为真时的返回值、条件为假时的返回值。你只写了ifelse(Y >0),缺了后面两个必填参数,这就是报错argument "yes" is missing, with no default的直接原因。lag()用法错误:你写的lag(Y,2,)多了个多余的逗号,而且lag()是用来取前N行的值,但你的需求是看当前行之后两年内是否有NA,完全不是一个逻辑方向,用lag()根本解决不了问题。- 逻辑缺失:你没考虑到规则里的「仅计数一次」——也就是同一个NA前两年内的多个
Y=1,只需要标记第一个为1,其他都为0。
接下来是符合你需求的解决方案,我们用dplyr来实现:
第一步:先整理样本数据
首先把你给出的样本数据转换成可操作的数据框:
library(dplyr) df <- tibble( year = c(1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011), country = rep("Bahamas", 22), Y = c(1,NA,NA,0,1,1,NA,1,NA,1,NA,1,1,0,NA,0,0,1,NA,1,1,1) )
第二步:实现虚拟变量X1的逻辑
我们的核心思路是:
- 先找到每个
NA的位置,确定它的「前两年区间」(即NA年份-2到NA年份-1) - 对落在这些区间内的
Y=1观测,只标记每个连续组的第一个为1,其他为0 - 不在区间内的观测,直接标记为0
代码如下:
df_result <- df %>% group_by(country) %>% # 第一步:找出所有NA的年份,存为列表 mutate(na_years = list(year[is.na(Y)])) %>% # 第二步:判断当前年份是否在任意一个NA的前两年区间内 mutate(in_na_window = purrr::map_lgl(na_years, ~ any(year %in% (.x - 2):(.x - 1)))) %>% # 第三步:把连续满足「Y=1且在NA前区间」的观测分成一组 mutate(group_id = cumsum(!(Y == 1 & in_na_window) | lag(!(Y == 1 & in_na_window), default = TRUE))) %>% # 第四步:每组内只把第一个Y=1的观测标记为1,其余为0 group_by(country, group_id) %>% mutate(X1 = ifelse(Y == 1 & in_na_window & row_number() == 1, 1, 0)) %>% # 清理临时列 ungroup() %>% select(-na_years, -in_na_window, -group_id)
验证结果
运行上述代码后,你可以用print(df_result)查看输出,结果完全匹配你给出的期望X1值:
# A tibble: 22 × 4 year country Y X1 <dbl> <chr> <dbl> <dbl> 1 1990 Bahamas 1 1 2 1991 Bahamas NA 0 3 1992 Bahamas NA 0 4 1993 Bahamas 0 0 5 1994 Bahamas 1 1 6 1995 Bahamas 1 0 7 1996 Bahamas NA 0 8 1997 Bahamas 1 1 9 1998 Bahamas NA 0 10 1999 Bahamas 1 1 11 2000 Bahamas NA 0 12 2001 Bahamas 1 1 13 2002 Bahamas 1 0 14 2003 Bahamas 0 0 15 2004 Bahamas NA 0 16 2005 Bahamas 0 0 17 2006 Bahamas 0 0 18 2007 Bahamas 1 1 19 2008 Bahamas NA 0 20 2009 Bahamas 1 0 21 2010 Bahamas 1 0 22 2011 Bahamas 1 0
补充说明
如果你没有安装purrr包,可以先运行install.packages("purrr")安装,它是tidyverse的一部分,用来处理列表操作非常方便。
内容的提问来源于stack exchange,提问作者Goulou
相关产品推荐
相关产品推荐

