简化R语言多列使用grepl与ifelse生成二元变量的方法
简化多列类别存在性二元变量的生成代码
你的现有实现确实重复度很高,写起来麻烦还不容易维护,这里有几种更简洁的方法来实现需求,代码量少还更灵活:
方法一:Base R 极简实现
先把所有工作行业的列提取出来,利用向量化操作一行搞定一个变量:
# 先还原你的数据集 names <- c("person1", "person2", "person3") job1_1_sector <- c("Private", "Public", "Private") job2_1_sector <- c(NA, "Public", "Private") job2_2_sector <- c("Private", "Public", "Other") job3_1_sector <- c("Private", "Private", "Private") job3_2_sector <- c("Other", "Public", "Other") job3_3_sector <- c("Private", NA, "Private") jobs <- cbind(job1_1_sector, job2_1_sector, job2_2_sector, job3_1_sector, job3_2_sector, job3_3_sector ) jobdata <- data.frame(names, jobs) # 提取所有行业列(排除name列) sector_cols <- jobdata[, -1] # 生成三个二元变量 jobdata$private <- as.integer(rowSums(sector_cols == "Private", na.rm = TRUE) > 0) jobdata$public <- as.integer(rowSums(sector_cols == "Public", na.rm = TRUE) > 0) jobdata$other <- as.integer(rowSums(sector_cols == "Other", na.rm = TRUE) > 0)
逻辑说明:
sector_cols == "Private"会生成一个布尔矩阵,每个单元格标记对应位置是否为PrivaterowSums(..., na.rm = TRUE)计算每行中Private出现的次数,na.rm=TRUE自动忽略NA值> 0判断该行是否至少出现一次目标类别,最后用as.integer把TRUE/FALSE转成1/0
方法二:批量生成(最适合多类别场景)
如果以后可能新增其他行业类别,用sapply批量处理更高效,只需要定义一次目标类别:
# 定义需要生成变量的目标行业 target_sectors <- c("Private", "Public", "Other") # 批量生成二元变量矩阵 new_vars <- sapply(target_sectors, function(sector) { as.integer(rowSums(sector_cols == sector, na.rm = TRUE) > 0) }) # 重命名列并合并到原数据集 colnames(new_vars) <- tolower(target_sectors) jobdata <- cbind(jobdata, new_vars)
这样不管你要生成多少个二元变量,只需要修改target_sectors这个向量就行,完全避免重复代码。
方法三:Tidyverse 风格(更易读易扩展)
如果你习惯用tidyverse生态的工具,用长格式转换的方式逻辑更清晰,扩展性也强:
library(dplyr) library(tidyr) # 转换为长格式,去重后转回宽格式生成二元变量 jobdata <- jobdata %>% pivot_longer(-names, values_to = "sector") %>% # 把所有行业列转成长格式 drop_na(sector) %>% # 去掉NA值的行 distinct(names, sector) %>% # 每个用户-行业只保留一条记录 mutate(flag = 1) %>% pivot_wider(names_from = sector, values_from = flag, values_fill = 0) %>% # 转回宽格式,缺省补0 rename_with(tolower) %>% # 把列名转成小写 right_join(jobdata, by = "names") # 合并回原数据集,保证所有用户都保留
这种方法的好处是,哪怕以后数据集里新增了NonProfit这类新行业,代码不需要做任何修改,运行后会自动生成对应的nonprofit二元变量。
以上三种方法的输出结果和你原来的代码完全一致,但代码简洁度和可维护性提升了很多,你可以根据自己的习惯选择~
内容的提问来源于stack exchange,提问作者imprela
相关产品推荐
相关产品推荐

