You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ID列合并多行数据:保留多列并求和指定列(R dplyr)

问题描述

我有一个临床研究的大型DataFrame(1000行×1000列),这里用健身房用户数据举例:每个用户有1条主数据行(包含900+个人信息列),每次到店对应1条访问行(记录各区域停留时间)。主数据行的时间列值为NA,访问行的主信息列值为NA,存在部分缺失值。

示例数据

#master row information#        #visit row information
gym_id  name    weight  height (900+ col data)  time_gym  time_sauna  time_cafe      
001     Alice   130     60         ...          NA        NA          NA              
001     Alice   NA      NA         ...          20        NA          10 
001     Alice   NA      NA         ...          60        NA          NA 
002     Bob     200     70         ...          NA        NA          NA                          
003     Eve     140     70         ...          NA        NA          NA
003     Eve     NA      NA         ...         100        10          NA
003     Eve     NA      NA         ...          80        NA          NA
003     Eve     NA      NA         ...          50        15          NA
003     Eve     NA      NA         ...          50        10          NA
003     Eve     NA      NA         ...          60        NA           5
003     Eve     NA      NA         ...          40        NA          NA
003     Eve     NA      NA         ...          80         5          NA

....

生成示例数据的代码

gym_id <- c(1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3)
name <- c('Alice', 'Alice', 'Alice', 'Bob', "Eve", "Eve", "Eve", "Eve", "Eve", "Eve", "Eve", "Eve")
weight <- c(130, NA, NA, 200, 140, NA, NA, NA, NA, NA, NA, NA)
height <- c(60, NA, NA, 70, 70, NA, NA, NA, NA, NA, NA, NA)
time_gym <- c(NA, 20, 60, NA, NA, 100, 80, 50, 50, 60, 40, 80)
time_sauna <- c(NA, NA, NA, NA, NA, 10, NA, 15, 10, NA, NA, 5)
time_cafe <- c(NA, 10, NA, NA, NA, NA, NA, NA, NA, 5, NA, NA)

gym <- data.frame(gym_id, name, weight, height, time_gym, time_sauna, time_cafe)

期望结果

#master row information#        #visit row information
gym_id  name    weight  height (900+ col data)  total_gym  total_sauna   total_cafe      
001     Alice   130     60         ...           80         0            10
002     Bob     200     70         ...            0         0             0
003     Eve     140     70         ...          460        40             5         

当前遇到的问题

尝试用mutate()、group_by()、summarise()组合时,会丢失大量列,比如:

gym %>%
  group_by(gym_id) %>%
  summarise(total_gym = sum(time_gym), total_sauna = sum(time_sauna))

逐个指定900+主信息列来保留不现实,拆分数据框的临时方案会给后续分析带来麻烦,求高效解决方法。


解决方案

可以利用dplyr的group_by()结合across()批量处理两类列,无需逐个指定列名:

简洁实现代码

library(dplyr)

gym_merged <- gym %>%
  # 按用户唯一标识分组(用gym_id+name避免重名冲突)
  group_by(gym_id, name) %>%
  summarise(
    # 批量处理主信息列:取每组中非NA的唯一有效值(主数据行仅1条有效数据)
    across(-starts_with("time_"), ~ first(na.omit(.))),
    # 批量计算时间列总和,自动添加total_前缀,NA自动按0计算
    across(starts_with("time_"), ~ sum(., na.rm = TRUE), .names = "total_{.col}")
  ) %>%
  # 把total_time_前缀简化为total_
  rename_with(~ gsub("total_time_", "total_", .), starts_with("total_time_")) %>%
  ungroup()

关键细节说明

  • across(-starts_with("time_")):通过排除时间列,直接批量处理所有主信息列,不用手动输入900+列名;如果主信息列有统一前缀,也可以用starts_with("主信息前缀")精准匹配
  • sum(., na.rm = TRUE):求和时忽略NA,确保没有访问记录的用户总和显示为0
  • .names = "total_{.col}":自动给求和后的列添加total_前缀,无需手动改名

这个方法高效处理批量列,同时保留所有主信息,完全符合需求。

内容的提问来源于stack exchange,提问作者Sam K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:47:57