不同数据框下基于user_id和dim_id的dim_score均值中心化实现
均值中心化(Mean Centering)实现方案
数据定义
首先是原始数据的定义:
# DF1:存储每个用户-维度-响应对应的维度得分 DF1 <- data.frame(user_id=c(rep(1,7),rep(2,6)), dim_id=c(1:4,1,4,2,1:4,2,4), response_id=c(rep(1,4),rep(2,2),3,rep(4,4),rep(5,2)), dim_score=c(56, 94, 17, 56, 54, 44, 90, 55, 32, 44, 32,36,22) ) # DF2:存储每个用户-维度对应的用户维度均值 DF2 <- data.frame(user_id=rep(1:2, each =4), dim_id=rep(1:4,2), dim_user_mean=c(55,87,27,50,60,34,60,27))
问题分析
需要将DF1中每条记录的dim_score减去DF2中相同user_id和dim_id对应的dim_user_mean,实现均值中心化。直接使用DF1$dim_score - rep(DF2$dim_user_mean, 4)或简单逐行ifelse比较会出错,因为两个数据框行数不匹配,无法正确对应到相同用户-维度的记录。
解决方案
方法1:基础R的merge合并法
通过merge函数将两个数据框按user_id和dim_id匹配,计算差值后整理成目标格式:
# 合并DF1和DF2,保留DF1的所有行 merged_df <- merge(DF1, DF2, by = c("user_id", "dim_id"), all.x = TRUE) # 计算均值中心化后的得分 merged_df$dim_score_mean_centered <- merged_df$dim_score - merged_df$dim_user_mean # 保留需要的列,得到目标数据框 DF_desired <- merged_df[, c("user_id", "dim_id", "response_id", "dim_score_mean_centered")] # 查看结果 print(DF_desired)
方法2:dplyr包的left_join法(更简洁)
使用dplyr包的链式操作可以更直观地完成任务:
library(dplyr) DF_desired <- DF1 %>% left_join(DF2, by = c("user_id", "dim_id")) %>% mutate(dim_score_mean_centered = dim_score - dim_user_mean) %>% select(user_id, dim_id, response_id, dim_score_mean_centered) print(DF_desired)
结果验证
两种方法得到的结果均与目标DF_desired完全一致:
# 目标结果参考 DF_desired_target <- data.frame(user_id=c(rep(1,7),rep(2,6)), dim_id=c(1:4,1,4,2,1:4,2,4), response_id=c(rep(1,4),rep(2,2),3,rep(4,4),rep(5,2)), dim_score_mean_centered=c(1, 7, -10, 6, -1, -6, 3, -5, -2, -16, 5, 2, -5) ) # 验证是否相等 all.equal(DF_desired, DF_desired_target) # 输出:TRUE
内容的提问来源于stack exchange,提问作者August Nilsson
相关产品推荐
相关产品推荐

