R语言中如何判断列B值是否在列A字符串中并生成虚拟变量?
解决虚拟变量生成的问题
我来帮你搞定这个需求!先理清楚你之前的代码为什么没得到预期结果,再给你几个高效的实现方法。
先重现你的数据
首先咱们把你的数据框建出来,方便测试:
df <- data.frame( A = rep("2012,2013,2014", 5), B = c("2011", "2012", "2013", "2014", "2015"), stringsAsFactors = FALSE )
为什么之前的代码不对?
- 你用
df$dummy <- ifelse(df$B %in% df$A, 1, 0)得到全1,是因为%in%的逻辑是检查每个B的元素是否存在于整个A向量中,而不是对应行的A字符串里。你的A列全是同一个字符串,这个判断逻辑完全不符合你的需求。 - 用
any(df$A==df$B)得到全TRUE,是因为any()会把整个向量的比较结果合并成一个单个的逻辑值(只要有一个匹配就返回TRUE),然后这个单一值会被重复填充到整个dummy列,自然全是TRUE了。
高效解决方案
方法1:Base R 逐行处理(简单直观)
用apply逐行遍历,把每行的A字符串拆分成年份向量,再检查B是否在其中:
df$dummy <- apply(df, 1, function(row) { # 拆分当前行的A为年份向量 year_list <- strsplit(row[["A"]], ",")[[1]] # 判断B是否在列表中,转成1/0 as.integer(row[["B"]] %in% year_list) })
方法2:stringr包向量化处理(大数据更高效)
如果你的数据量比较大,逐行的apply效率会偏低,用stringr的向量化函数速度更快:
library(stringr) # fixed()确保按固定字符串匹配,避免正则特殊字符干扰 df$dummy <- as.integer(str_detect(df$A, fixed(df$B)))
这个方法是向量化操作,不需要逐行循环,处理大表格的时候优势很明显。
方法3:data.table(超大数据最优选择)
如果是处理百万级别的大数据框,data.table的性能是最好的:
library(data.table) # 转成data.table格式 setDT(df) # 生成dummy列 df[, dummy := as.integer(str_detect(A, fixed(B)))]
最终结果
不管用哪种方法,你都会得到预期的结果:
A B dummy 1 2012,2013,2014 2011 0 2 2012,2013,2014 2012 1 3 2012,2013,2014 2013 1 4 2012,2013,2014 2014 1 5 2012,2013,2014 2015 0
内容的提问来源于stack exchange,提问作者Ian Wang
相关产品推荐
相关产品推荐

