如何在R语言中为带权重的调查数据应用权重?
调查数据加权处理问题
我有带权重的调查数据,权重代表样本中单个个体对应的总体人数。现在不对数据加权的话,结果没法准确代表总体,想找个简单的方法把权重纳入分析里。是不是要把观测值乘以权重?我看了相关视频,但视频里都是分层数据,我的是个体数据,没找到解决办法,求帮忙。
原始示例代码
ID <- c(1,2,3,4,5,6,7,8,9,10,11,12, 13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32,33,34,35,36) year <- c(1980,1980,1980,1981,1982,1982,1980,1980,1981,1981,1982,1982, 1980,1980,1980,1981,1982,1982,1980,1980,1981,1981,1982,1982, 1980,1980,1980,1981,1982,1982,1980,1980,1981,1981,1982,1982) city <- c("NY","NY","NY","NY","NY","NY","NY","NY","NY","NY","NY","NY", "NY","NY","NY","NY","NY","NY","NY","NY","NY","NY","NY","NY", "CA","CA","CA","CA","CA","CA","CA","CA","CA","CA","CA","CA") district <- c(1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2, 1,2,1,2,1,2,1,2,1,2,1,2) weight <- c(100,17,25,1,100,52,10,5,90,10,10,15, 13,1,25,1,6,52,10,5,90,7,10,15, 1,2,3,4,5,6,10,20,3,40,50,6) df <- data.frame(ID,year,city,district,weight) df$year <- as.factor(df$year) df$district <- as.factor(df$district) print(df) # aggregate count by year, city and district a <- aggregate(ID ~ year + city + district, data = df, FUN = length) colnames(a)[colnames(a) == 'ID'] <- 'numObs' # add new Total column, populate total by year a[a$year == 1980, "TotalforYear"] <- with(a, sum(numObs[year == 1980])) a[a$year == 1981, "TotalforYear"] <- with(a, sum(numObs[year == 1981])) a[a$year == 1982, "TotalforYear"] <- with(a, sum(numObs[year == 1982])) # add new column called share and initialize it a[ , 'share'] <- 0 a$share = (a$numObs/a$TotalforYear) # add group column a[a$district == 1 & a$city == 'NY', "group"] <- 'NY district1' a[a$district == 2 & a$city == 'NY', "group"] <- 'NY district2' a[a$district == 1 & a$city == 'CA', "group"] <- 'CA district1' a[a$district == 2 & a$city == 'CA', "group"] <- 'CA district2' a g1 <- ggplot(a, aes(x=year, y=share, group=group)) + geom_line(aes(linetype=group), color = 'red', size = 0.8) + geom_point(aes(shape=group), size = 2) + theme_classic() + theme(legend.position="bottom", panel.grid.major.x = element_line( linewidth=.1, color="grey93" ), panel.grid.major.y = element_line( linewidth=.1, color="grey93" ) ) + ylab("Share") + scale_linetype_manual(values=c("solid", "dotted", 'dashed', 'longdash')) + theme(legend.title=element_blank()) g1
加权处理解决方案
核心逻辑
你的思路是对的,加权的本质就是用个体权重替代原始观测计数,通过求和分组内的权重得到该分组对应的总体规模,再基于这个规模计算占比,结果就能准确代表总体。不需要手动给每个观测值乘权重,直接对权重求和效率更高。
具体修改步骤
1. 计算分组加权总和
替换原代码中的aggregate步骤,不再统计原始观测数,而是对每个year+city+district分组的weight求和,得到该分组对应的总体人数:
# 计算加权后的分组总体人数 a_weighted <- aggregate(weight ~ year + city + district, data = df, FUN = sum) colnames(a_weighted)[colnames(a_weighted) == 'weight'] <- 'weighted_total'
2. 计算年度加权总人数
基于分组加权总和,计算每年的总体总人数:
# 计算每年的加权总人数(用ave函数更简洁) a_weighted$TotalforYear <- with(a_weighted, ave(weighted_total, year, FUN = sum))
3. 计算加权占比
用分组加权总和除以年度加权总数,得到能代表总体的占比:
# 计算加权占比 a_weighted$share <- a_weighted$weighted_total / a_weighted$TotalforYear
4. 添加分组标签(和原代码逻辑一致)
# 添加group列 a_weighted[a_weighted$district == 1 & a_weighted$city == 'NY', "group"] <- 'NY district1' a_weighted[a_weighted$district == 2 & a_weighted$city == 'NY', "group"] <- 'NY district2' a_weighted[a_weighted$district == 1 & a_weighted$city == 'CA', "group"] <- 'CA district1' a_weighted[a_weighted$district == 2 & a_weighted$city == 'CA', "group"] <- 'CA district2'
5. 绘制加权后的图表
直接使用加权后的数据集绘图,代码逻辑和原图表一致,仅修改数据源:
g1_weighted <- ggplot(a_weighted, aes(x=year, y=share, group=group)) + geom_line(aes(linetype=group), color = 'red', size = 0.8) + geom_point(aes(shape=group), size = 2) + theme_classic() + theme(legend.position="bottom", panel.grid.major.x = element_line( linewidth=.1, color="grey93" ), panel.grid.major.y = element_line( linewidth=.1, color="grey93" ) ) + ylab("加权占比") + scale_linetype_manual(values=c("solid", "dotted", 'dashed', 'longdash')) + theme(legend.title=element_blank()) g1_weighted
关键说明
- 这个方法完全适配你的个体数据,不需要额外的分层信息,只要每个样本都有对应的权重即可。
- 加权后的占比反映的是总体中各分组的真实比例,而非样本中的比例,解决了样本代表性偏差的问题。
内容的提问来源于stack exchange,提问作者ithoughtso
相关产品推荐
相关产品推荐

