使用apply与regexpr为DataFrame新增多列的技术求助
嘿,我来帮你搞定这个给DataFrame批量生成颜色标记列的需求!先从模拟你的数据场景开始,再给你两种靠谱的实现方法,顺便聊聊你用regexpr可能踩的坑。
先模拟你的数据场景
假设你的DataFrame和颜色列表是这样的:
# 模拟原始DataFrame df <- data.frame( product_id = c(1, 2, 3), colors = c("红色,蓝色", "绿色,红色", "黄色") ) # 你的目标颜色列表 target_colors <- c("红色", "蓝色", "绿色", "黄色")
方法1:用tidyverse(直观易读,适合复杂数据操作)
如果习惯用tidyverse工具链,这个方法逻辑清晰,一步到位就能生成你要的结果:
library(tidyverse) df_result <- df %>% # 把逗号分隔的颜色拆成每行一个 separate_rows(colors, sep = ",") %>% # 标记该颜色存在为1 mutate(exists = 1) %>% # 转成宽表,缺失的颜色自动补0 pivot_wider( names_from = colors, values_from = exists, values_fill = 0 ) print(df_result)
运行后会得到你想要的输出:
# A tibble: 3 × 5 product_id 红色 蓝色 绿色 黄色 <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 1 1 0 0 2 2 1 0 1 0 3 3 0 0 0 1
方法2:用Base R(轻量无需额外包)
如果不想加载tidyverse,用Base R的lapply结合grepl也能实现,这应该和你尝试的方向接近:
df_base <- df # 遍历颜色列表,给每个颜色生成一列0/1标记 df_base[target_colors] <- lapply(target_colors, function(color) { # grepl检查是否包含该颜色,转成整数0/1 as.integer(grepl(color, df_base$colors, fixed = TRUE)) }) print(df_base)
这里要注意fixed = TRUE,它会把颜色当成纯文本匹配,避免因为颜色里有正则特殊字符(比如.、*)导致的意外匹配——这可能是你之前用regexpr出错的原因之一!
修复你用regexpr的尝试
如果坚持想用regexpr,只要把匹配结果转换成0/1,同时加上fixed = TRUE就能正常运行了:
df_regex <- df df_regex[target_colors] <- lapply(target_colors, function(color) { # regexpr返回匹配位置,>0表示存在,转成0/1 as.integer(regexpr(color, df_regex$colors, fixed = TRUE) > 0) })
两种方法都能生成你要的结果,选哪种看你的习惯就行~
内容的提问来源于stack exchange,提问作者Thomas AMET
相关产品推荐
相关产品推荐

