如何使用R中的自定义函数聚合data.frame中的多个列?

时间:2017-10-10 13:26:03

标签: r dataframe aggregate

我有一个data.frame 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 个答案:

答案 0 :(得分:3)

您与aggregate函数非常接近,您需要调整聚合处理NA的方式(从na.omitna.pass)。我的猜测是聚合首先删除NA的所有行,然后进行聚合,而不是删除NAs,因为聚合迭代要聚合的列。由于您的示例数据帧在每行中都有NA,因此您最终会得到一个0行数据帧(这是我在运行代码时遇到的错误)。我通过删除除了一个NA以外的所有NA来测试它,并且您的代码按原样运行。因此,我们设置na.action = na.pass以通过NA。

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

原始答案

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

答案 1 :(得分: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 :(得分: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

答案 3 :(得分:2)

只需在na.action=na.pass电话中添加aggregate()

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

答案 4 :(得分: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))

返回:

# 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