如何在R中利用数据框两列值匹配获取对应BMI值并计算差值
计算App用户的BMI变化量解决方案
原代码问题分析
你尝试的代码存在作用域错误:在mutate中直接调用filter(weight_log$BMI, Id == Id & date_min == Date)时,Id和date_min是当前分组的变量,但weight_log$BMI是整个数据集的变量,导致条件Id == Id永远为真,无法正确关联到当前用户的对应日期记录,最终得到错误的BMI值。
正确实现方法
方法1:分组筛选最早/最晚记录后合并(最清晰)
通过slice_min()和slice_max()分别提取每个用户最早、最晚日期的BMI记录,再通过left_join合并计算差值:
BMI_results <- weight_log %>% # 获取每个用户最早日期的BMI group_by(Id) %>% slice_min(Date, n = 1) %>% select(Id, first_BMI = BMI) %>% # 合并最晚日期的BMI left_join( weight_log %>% group_by(Id) %>% slice_max(Date, n = 1) %>% select(Id, last_BMI = BMI), by = "Id" ) %>% # 计算BMI变化量(末次 - 首次) mutate(BMI_difference = last_BMI - first_BMI)
方法2:分组排序后直接取首尾值(最简洁)
先对每个用户的记录按日期排序,再用first()和last()直接提取首尾BMI值:
BMI_results <- weight_log %>% group_by(Id) %>% arrange(Date) %>% # 按日期升序排序,确保first是最早记录 summarize( date_min = first(Date), date_max = last(Date), first_BMI = first(BMI), last_BMI = last(BMI), BMI_difference = last_BMI - first_BMI )
方法3:分组标记首尾日期后转宽表(适合多字段需求)
如果需要同时保留更多字段信息,可以先标记首尾日期,再通过pivot_wider整理成宽表:
BMI_results <- weight_log %>% group_by(Id) %>% mutate( date_min = min(Date), date_max = max(Date) ) %>% # 筛选出最早和最晚的记录行 filter(Date == date_min | Date == date_max) %>% # 转宽表,区分首尾记录 pivot_wider( id_cols = Id, names_from = ifelse(Date == date_min, "first", "last"), values_from = c(Date, BMI) ) %>% # 计算变化量并整理列顺序 mutate(BMI_difference = last_BMI - first_BMI) %>% select(Id, date_min = Date_first, date_max = Date_last, first_BMI, last_BMI, BMI_difference)
内容的提问来源于stack exchange,提问作者Enrique Dominguez
相关产品推荐
相关产品推荐

