R中如何根据长度不同的另一数据框的值生成虚拟变量
解决方案
方法1:tidyverse实现(推荐,无需循环,效率更高)
首先构造示例数据,再通过左连接+逻辑判断直接生成虚拟变量:
library(dplyr) # 构造示例Df1 Df1 <- data.frame( id = c(rep(1,5), rep(2,4)), year = c(2017:2021, 2018:2021), x1 = c(0.3, 0.5, 0.45, 0.5, 0.6, 0.2, 0.3, 0.4, 0.5) ) # 构造示例Df2 Df2 <- data.frame( id = c(1,2), year = c(2019, 2020) ) # 生成目标数据框Df3 Df3 <- Df1 %>% left_join(Df2, by = "id", suffix = c("", "_ref")) %>% mutate(dummy = as.integer(year >= year_ref)) %>% select(-year_ref)
对应你实际的数据集,直接替换列名即可:
# 假设你两个原始表分别为: # df_all:存所有id+年份的观测,对应原描述里的Df1 # df_implement:存每个id对应的实施年份,对应原描述里的Df2 data_school <- df_all %>% left_join(df_implement, by = "id_escola", suffix = c("", "_ref")) %>% mutate(internet_fixa = as.integer(ano >= ano_ref)) %>% select(-ano_ref)
方法2:base R实现
# 匹配每个id对应的参考年份 Df1$year_ref <- Df2$year[match(Df1$id, Df2$id)] # 生成虚拟变量 Df1$dummy <- as.integer(Df1$year >= Df1$year_ref) # 移除辅助列得到Df3 Df3 <- Df1[, !names(Df1) %in% "year_ref"]
原有循环报错原因&修复方案
报错核心原因是:部分id对应的current_subset(非NA的internet_fixa行)为空,导致year_implementation长度为0,if判断时找不到比较对象就抛出长度为0的错误。
如果一定要用循环实现,可添加非空判断简化逻辑:
for (id in unique(data_school$id_escola)) { current_subset <- subset(data_school, id_escola == id & !is.na(internet_fixa)) # 跳过没有参考年份的id if(nrow(current_subset) == 0) next # 提取唯一参考年份,避免多值冲突 year_implementation <- unique(current_subset$ano)[1] # 批量替换当前id的所有行,无需内层循环 idx <- data_school$id_escola == id data_school$internet_fixa[idx] <- as.integer(data_school$ano[idx] >= year_implementation) }
内容的提问来源于stack exchange,提问作者José Eduardo Puentes Arteta
相关产品推荐
相关产品推荐

