如何基于变量x1及相邻x2生成指定规则的dummy变量?
问题描述
以下是用于演示的数据框生成代码:
d<-data.frame(x1=c(rep("no",5),rep("yes",4),rep("no",2),rep("yes",3),rep("no",2),rep("yes",3)), x2=c(rep("no",6),rep("yes",1),rep("no",9),rep("yes",2),rep("no",1)), dummy=c(rep(0,5),rep(1,4),rep(0,5),rep(0,2),rep(1,3)))
我拥有两个变量x1和x2,希望基于这两个指示变量生成一个名为'dummy'的dummy变量。具体规则为:当x1取值为"yes",且其所在的连续x1="yes"集群中至少有一个x2取值为"yes"时,dummy取值为1;若x1取值为"yes"但所在集群的x2均为"no",则dummy取值为0。
使用以下代码可以生成x1和x2同时为"yes"时取值为1的dummy变量:
d$dummy=ifelse(d$x1=="yes" & d$x2=="yes",1,0)
但该方法无法捕捉到连续的x1="yes"集群,而这正是我需要实现的效果。
我期望的输出示例如下:
请问该如何实现这一需求?
解决方案
可以通过分组标记连续x1集群+检查集群内是否存在x2=yes的思路实现,以下提供两种高效方法:
方法一:使用dplyr简洁实现(推荐)
利用分组函数识别连续的x1="yes"块,再判断每个块内是否包含x2="yes",最后生成dummy变量:
library(dplyr) # 生成演示数据 d <- data.frame( x1 = c(rep("no",5), rep("yes",4), rep("no",2), rep("yes",3), rep("no",2), rep("yes",3)), x2 = c(rep("no",6), rep("yes",1), rep("no",9), rep("yes",2), rep("no",1)) ) d <- d %>% # 给连续的x1集群分配唯一分组ID mutate(group_id = cumsum(x1 != lag(x1, default = ""))) %>% # 按分组检查是否存在x2=yes group_by(group_id) %>% mutate(has_x2_yes = any(x2 == "yes")) %>% # 按规则生成dummy mutate(dummy = ifelse(x1 == "yes" & has_x2_yes, 1, 0)) %>% ungroup() %>% select(-group_id, -has_x2_yes) print(d)
方法二:基础R实现(无需额外包)
如果不想加载第三方包,可通过位置扩展和范围合并实现:
# 生成演示数据 d <- data.frame( x1 = c(rep("no",5), rep("yes",4), rep("no",2), rep("yes",3), rep("no",2), rep("yes",3)), x2 = c(rep("no",6), rep("yes",1), rep("no",9), rep("yes",2), rep("no",1)) ) # 标记所有x2=yes的位置 x2_yes_pos <- which(d$x2 == "yes") # 找到每个x2=yes所在的x1集群范围 get_cluster_range <- function(pos) { left <- pos while(left > 1 && d$x1[left-1] == "yes") left <- left - 1 right <- pos while(right < nrow(d) && d$x1[right+1] == "yes") right <- right + 1 c(left, right) } cluster_ranges <- lapply(x2_yes_pos, get_cluster_range) # 合并重叠的集群范围 if(length(cluster_ranges) > 0) { merged <- do.call(rbind, cluster_ranges) merged <- merged[order(merged[,1]),] current <- merged[1,] final_ranges <- list() for(i in 2:nrow(merged)) { if(merged[i,1] <= current[2] + 1) { current[2] <- max(current[2], merged[i,2]) } else { final_ranges <- c(final_ranges, list(current)) current <- merged[i,] } } final_ranges <- c(final_ranges, list(current)) } # 生成dummy变量 d$dummy <- 0 for(rng in final_ranges) { d$dummy[rng[1]:rng[2]] <- 1 } d$dummy <- ifelse(d$x1 == "yes", d$dummy, 0) print(d)
两种方法都能精准匹配需求,将连续x1="yes"且集群内存在x2="yes"的行标记为1,其余x1="yes"行标记为0。
内容的提问来源于stack exchange,提问作者Rei
相关产品推荐
相关产品推荐

