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

基于name+year分组合并同一DataFrame行的R语言高效实现方法

优雅压缩分组后的DataFrame(合并同组多行到单行)

你这个需求太典型啦——把同一分组(name+year)下分散在多行的非NA值合并到同一行,完全不用绕弯子做过滤连接,用分组聚合的思路就能高效解决,下面给你几种常用的方案:

1. 用tidyverse/dplyr(最常用的语法风格)

如果平时用tidyverse生态,这个方法最直观,先按name和year分组,然后对每一列提取非NA的值:

library(dplyr)

df_compressed <- df %>%
  group_by(name, year) %>%
  summarise(across(A:C, ~ na.omit(.)[1]), .groups = "drop")
  • group_by(name, year):指定分组依据
  • across(A:C, ~ na.omit(.)[1]):对A到C的每一列,先去掉NA值,再取第一个元素(因为每个组里每个列只有1个非NA值)
  • .groups = "drop":分组后取消分组状态,得到普通DataFrame

运行后就能得到你想要的结果:

# A tibble: 2 × 5
  name   year     A     B     C
  <chr> <dbl> <dbl> <dbl> <dbl>
1 bar      18     2     4     5
2 foo      19     1     3     2

2. 用data.table(大数据场景更高效)

如果你的DataFrame行数特别多,data.table的速度优势会很明显:

library(data.table)

setDT(df)
df_compressed <- df[, lapply(.SD, function(x) na.omit(x)[1]), by = .(name, year)]
  • setDT(df):把普通DataFrame转成data.table格式
  • lapply(.SD, function(x) na.omit(x)[1]):对每个分组的所有列(.SD代表Subset of Data)执行提取非NA值的操作
  • by = .(name, year):指定分组键

3. Base R原生方法(不用加载额外包)

如果不想加载第三方包,用base R的aggregate函数也能搞定:

df_compressed <- aggregate(. ~ name + year, data = df, FUN = function(x) na.omit(x)[1])
  • . ~ name + year:表示把除了name和year之外的所有列,按这两列分组聚合
  • FUN = function(x) na.omit(x)[1]:自定义聚合函数,提取非NA值

这三种方法都能完美实现你的需求,相比过滤连接,代码更简洁,效率也更高——尤其是data.table版本,处理几十万甚至上百万行数据的时候优势很明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 12:07:34