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

如何基于分组变量合并含数值与字符列的R数据框行?

按ID聚合含数值与字符列的数据框

我有一份需要按ID字段聚合的数据框,其中同时包含数值型和字符型列。R原生的aggregate()函数无法处理字符型列,我自己写了循环实现,但不够优雅,希望得到更简便高效的方法,优先用R基础包或data.table包的方案,也接受其他包的实现。

示例数据

id winter wintercolor spring springcolor summer summercolor fall fallcolor
 1:  a      3        blue     NA        <NA>     NA        <NA>   NA      <NA>
 2:  a     NA        <NA>      4      purple     NA        <NA>   NA      <NA>
 3:  a     NA        <NA>     NA        <NA>      2       brown   NA      <NA>
 4:  a     NA        <NA>     NA        <NA>     NA        <NA>    5       red
 5:  b     NA        <NA>      4      yellow     NA        <NA>   NA      <NA>
 6:  b     NA        <NA>     NA        <NA>     NA        <NA>    2      blue
 7:  c      4         red     NA        <NA>     NA        <NA>   NA      <NA>
 8:  c     NA        <NA>     NA        <NA>      6      orange   NA      <NA>
 9:  c     NA        <NA>     NA        <NA>     NA        <NA>    3      blue
10:  d      5         red     NA        <NA>     NA        <NA>   NA      <NA>
11:  d     NA        <NA>     NA        <NA>      1        blue   NA      <NA>

期望结果

id winter wintercolor spring springcolor summer summercolor fall fallcolor
1:  a      3        blue      4      purple      2       brown    5       red
2:  b     NA        <NA>      4      yellow     NA        <NA>    2      blue
3:  c      4         red     NA        <NA>      6      orange    3      blue
4:  d      5         red     NA        <NA>      1        blue   NA      <NA>

现有循环实现代码

library(data.table)
id <- c('a','a','a','a','b','b','c','c','c','d','d')
winter <- c(3,NA,NA,NA,NA,NA,4,NA,NA,5,NA)
wintercolor <- c('blue',NA,NA,NA,NA,NA,'red',NA,NA,'red',NA)
spring <- c(NA,4,NA,NA,4,NA,NA,NA,NA,NA,NA)
springcolor <- c(NA,'purple',NA,NA,'yellow',NA,NA,NA,NA,NA,NA)
summer <- c(NA,NA,2,NA,NA,NA,NA,6,NA,NA,1)
summercolor <- c(NA,NA,'brown',NA,NA,NA,NA,'orange',NA,NA,'blue')
fall <- c(NA,NA,NA,5,NA,2,NA,NA,3,NA,NA)
fallcolor <- c(NA,NA,NA,'red',NA,'blue',NA,NA,'blue',NA,NA)

sampledat <- data.table(id,winter,wintercolor,spring,springcolor,summer,summercolor,fall,fallcolor)
setkey(sampledat,id)

colsets <- c('winter','spring','summer','fall')
nnn <- length(colsets)
holder <- vector('list',nnn)
for(i in 1:nnn){
#i=1
    loopcols <- c('id',names(sampledat)[grepl(colsets[i],names(sampledat))])
    loopdat <- sampledat[,loopcols, with=F]
    col2 <- as.name(loopcols[2])
    col3 <- as.name(loopcols[3])
    holder[[i]] <- loopdat[!is.na(eval(col2)) & !is.na(eval(col3))]
}

combodat <- Reduce(function(x, y) merge(x, y, by='id', all=T), holder)
combodat

解决方案

1. data.table简洁实现

利用data.table的按组操作,直接提取每组各列的第一个非NA值(每个ID对应每个季节的字段仅有一个有效非NA值):

library(data.table)
result_dt <- sampledat[, lapply(.SD, function(x) x[!is.na(x)][1]), by = id]
result_dt

2. R基础包实现

自定义适配数值/字符列的聚合函数,配合aggregate()使用:

# 自定义聚合函数:提取第一个非NA值
agg_fun <- function(x) {
  non_na <- x[!is.na(x)]
  if(length(non_na) > 0) non_na[1] else NA
}

# 按ID聚合所有列
result_base <- aggregate(. ~ id, data = sampledat, FUN = agg_fun)
result_base

3. dplyr包实现

用tidyverse系列的dplyr分组汇总,代码更直观:

library(dplyr)
result_dplyr <- sampledat %>%
  group_by(id) %>%
  summarise(across(everything(), ~ .x[!is.na(.x)][1]), .groups = "drop")
result_dplyr

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:24:29