R语言:按列表更新列值的归一化函数报错问题求助
人口统计数据集分组归一化问题处理
需求说明
对人口统计计数数据集的相似列分组执行归一化:将分组内每列的行值除以该分组的行总和,更新对应列。例如gender组(包含male和female列),每列值需除以该行male+female的总和。
分组定义
gender <- c("male","female") income <- c("income_0_50k","income_50k_100k","income_over_100k")
问题代码及报错
编写的归一化函数及调用方式:
percent.total <- function(df,x){ tot <- rowSums(df[x]) for(i in 1:length(x)){ df[x[i]] <- df[x[i]]/tot } } percent.total(dat,gender)
执行后报错:
Error in Ops.data.frame(df[x[i]], df[x]) :
‘/’ only defined for equally-sized data frames
测试情况
在函数外单独测试时,i=1可正常运行,但i=2失败:
i <- 1 tot <- rowSums(dat[gender]) dat[gender[i]] <- dat[gender[i]]/tot
样本数据
注意:样本数据包含千分位逗号,需先转换为数值型:
# 原始样本数据 dat <- data.frame( male = c("1,487", "726", "632", "655", "616", "1,945", "888"), female = c("1,501", "810", "615", "692", "599", "1,544", "980"), stringsAsFactors = FALSE ) # 转换为数值型 dat$male <- as.numeric(gsub(",", "", dat$male)) dat$female <- as.numeric(gsub(",", "", dat$female))
期望输出
male female 1 0.497657296 0.502342704 2 0.472656250 0.527343750 3 0.506816359 0.493183641 4 0.486265776 0.513734224 5 0.506995885 0.493004115 6 0.557466323 0.442533677 7 0.475374732 0.524625268
解决方案
问题原因
df[x[i]]返回的是数据框类型,而tot是向量,R中不支持数据框与向量直接做除法,这是报错的核心原因。此外,R函数默认不会修改传入的原始数据框,需返回修改后的结果。
修改后的函数(循环版)
将df[x[i]]改为df[[x[i]]](提取向量),并返回修改后的数据框:
percent.total <- function(df, x){ tot <- rowSums(df[x]) for(i in seq_along(x)){ df[[x[i]]] <- df[[x[i]]] / tot } return(df) } # 调用并覆盖原数据框 dat <- percent.total(dat, gender)
更高效的向量化写法(推荐)
利用R的广播特性,无需循环直接处理整个分组列:
percent.total <- function(df, x){ df[x] <- df[x] / rowSums(df[x]) return(df) } # 调用 dat <- percent.total(dat, gender)
验证结果
执行上述代码后,dat将输出与期望一致的归一化结果。
内容的提问来源于stack exchange,提问作者Kyle Bailey
相关产品推荐
相关产品推荐

