如何在 R 中使用自定义函数聚合数据框中的多列?

3

我有一个数据框 dt,其中包含一些重复的键和缺失的数据,例如:

Name     Height     Weight   Age
Alice    180        NA       35
Bob      NA         80       27
Alice    NA         70       NA
Charles  170        75       NA

在这种情况下,关键是名称,我想对每一列应用类似的函数。
f <- function(x){
  x <- x[!is.na(x)]
  x <- x[1]
  return(x)
  }

在按键(即“名称”列)聚合的同时,以便获得结果

Name     Height     Weight   Age
Alice    180        70       35
Bob      NA         80       27
Charles  170        75       NA

我尝试了

dt_agg <- aggregate(. ~ Name,
                    data = dt,
                    FUN = f)

我遇到了一些错误,然后我尝试了以下操作:

dt_agg_1 <- aggregate(Height ~ Name,
                      data = dt,
                      FUN = f)

dt_agg_2 <- aggregate(Weight ~ Name,
                      data = dt,
                      FUN = f)

这次终于成功了。

由于我有50列,第二种方法对我来说相当麻烦。有没有一种方法可以修复第一种方法?

谢谢帮助!

5个回答

3

你接近了aggregate函数的正确用法,但需要调整aggregateNA值的处理方式(从na.omit改为na.pass)。我猜想aggregate在聚合数据之前会先删除所有带有NA的行,而不是在迭代要聚合的列时删除NA。由于你的示例数据框中每一行都有一个NA值,因此最终生成了0行数据框(这就是当运行你的代码时出现错误的原因)。通过只保留一个NA并测试,我证实了这一点,你可以直接使用你的代码。因此,我们需要设置na.action=na.pass以使NA值被传递。

dt_agg <- aggregate(. ~ Name,
                    data = dt,
                    FUN = f, na.action = "na.pass")

original answer

dt_agg <- aggregate(dt[, -1], 
                    by = list(dt$Name),
                    FUN = f)
dt_agg
# Group.1 Height Weight Age
# 1   Alice    180     70  35
# 2     Bob     NA     80  27
# 3 Charles    170     75  NA

2
你可以使用 dplyr 来完成这个任务:
library(dplyr)
df %>%
  group_by(Name) %>%
  summarize_all(funs(sort(.)[1]))

结果:

# A tibble: 3 x 4
     Name Height Weight   Age
   <fctr>  <int>  <int> <int>
1   Alice    180     70    35
2     Bob     NA     80    27
3 Charles    170     75    NA

数据:

df = read.table(text = "Name     Height     Weight   Age
Alice    180        NA       35
Bob      NA         80       27
Alice    NA         70       NA
Charles  170        75       NA", header = TRUE)

2

这里有一个使用 data.table 的选项

library(data.table)
setDT(df)[, lapply(.SD, function(x) head(sort(x), 1)), Name]
#      Name Height Weight Age
#1:   Alice    180     70  35
#2:     Bob     NA     80  27
#3: Charles    170     75  NA

2

只需在 aggregate() 调用中添加 na.action=na.pass

aggdf <- aggregate(.~Name, data=df, FUN=f, na.action=na.pass)
#      Name Height Weight Age
# 1   Alice    180     70  35
# 2     Bob     NA     80  27
# 3 Charles    170     75  NA

1
如果您在函数中添加一个ifelse(),以确保当所有值都为NA时函数返回一个值:
f <- function(x) {
  x <- x[!is.na(x)]
  ifelse(length(x) == 0, NA, x)
}

您可以使用 dplyr 进行聚合操作:
library(dplyr)
dt %>% group_by(Name) %>% summarise_all(funs(f))

This returns:

# A tibble: 3 x 4
     Name Height Weight   Age
   <fctr>  <dbl>  <dbl> <dbl>
1   Alice    180     70    35
2     Bob     NA     80    27
3 Charles    170     75    NA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接