R中如何高效有条件批量填充DataFrame的多列需求字段
R语言批量填充DataFrame需求列的问题
现有数据结构
现有结构如下的DataFrame:
CustomerID Department Price SportswearDemand HomeDemand KidswearDemand WomenswearDemand ------------------------------------------------------------------------------------------- 1050091 Sportswear 497.6 0 0 0 0 1555018 Womenswear 336.0 0 0 0 0 210239 Womenswear 698.0 0 0 0 0 507556 Sportswear 209.0 0 0 0 0 1708193 Sportswear 209.0 0 0 0 0 1295733 Menswear 209.0 0 0 0 0 1213373 Sportswear 298.0 0 0 0 0 753471 Sportswear 209.0 0 0 0 0 82739 Menswear 349.0 0 0 0 0 1660995 Kidswear 424.6 0 0 0 0 . . .
将SportswearDemand及右侧的所有列统称为需求列,需要按照如下规则填充:若某行的Department值和需求列名称去掉Demand后缀的前缀匹配,则将该行的Price值填入对应需求列替换原有0值,否则保留0。
预期效果
填充完成后效果如下:
CustomerID Department Price SportswearDemand HomeDemand KidswearDemand WomenswearDemand ------------------------------------------------------------------------------------------- 1050091 Sportswear 497.6 497.6 0 0 0 1555018 Womenswear 336.0 0 0 0 336.0 210239 Womenswear 698.0 0 0 0 698.0 507556 Sportswear 209.0 209.0 0 0 0 1708193 Sportswear 209.0 209.0 0 0 0 1295733 Menswear 209.0 0 0 0 0 1213373 Sportswear 298.0 298.0 0 0 0 753471 Sportswear 209.0 209.0 0 0 0 82739 Menswear 349.0 0 0 0 0 1660995 Kidswear 424.6 0 0 424.6 0 . . .
现有实现的问题
硬编码逐列写入可以实现需求:
df$SportswearDemand <- with(df, ifelse(df$Department == "Sportswear", df$Price, 0)) df$HomeDemand <- with(df, ifelse(df$Department == "Home", df$Price, 0)) df$KidswearDemand <- with(df, ifelse(df$Department == "Kidswear", df$Price, 0)) df$WomenswearDemand <- with(df, ifelse(df$Department == "Womenswear", df$Price, 0))
但需求列有30个,逐行写重复代码效率过低。尝试用for循环批量处理时出现错误:
DemandColumns # 存储了全部30个需求列名称的字符串数组 for (i in DemandColumns){ df$i <- with(df, ifelse(df$Department == substr(i,1,nchar(i)-6), df$Price, 0)) }
运行后仅新增了一列名为i的全0字段,没有正确修改目标需求列。
错误原因
R语言中$运算符后的标识符会被直接当做固定列名解析,不会识别为变量的实际值,因此df$i永远是操作名为i的列,而非变量i存储的目标需求列名,导致循环逻辑错误。
修正方案
方案1:调整for循环写法
使用双括号[[]]替代$运算符,双括号支持解析变量内容作为列名,修正后代码如下:
# DemandColumns为你提前定义的所有需求列名的字符串数组 for (col_name in DemandColumns){ # 提取列名对应的部门名(去掉Demand后缀) dept_name <- substr(col_name, 1, nchar(col_name)-6) df[[col_name]] <- ifelse(df$Department == dept_name, df$Price, 0) }
方案2:tidyverse向量化写法(无需提前定义列名、无需循环)
如果使用tidyverse生态工具,可以自动匹配所有Demand后缀的列,代码更简洁高效:
library(dplyr) library(stringr) df <- df %>% # 遍历所有结尾为Demand的列,批量赋值 mutate(across(ends_with("Demand"), ~ifelse(Department == str_remove(cur_column(), "Demand$"), Price, 0)))
内容的提问来源于stack exchange,提问作者Parseval
相关产品推荐
相关产品推荐

