如何使用R中的自定义函数聚合data.frame中的多个列?
我有一个data.frame如何使用R中的自定义函数聚合data.frame中的多个列?,r,dataframe,aggregate,R,Dataframe,Aggregate,我有一个data.framedt,有一些重复的键和丢失的数据,即 Name Height Weight Age Alice 180 NA 35 Bob NA 80 27 Alice NA 70 NA Charles 170 75 NA 在本例中,键是名称,我想对每个列应用一个函数,如 f <- function(x){ x <-
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)
}
我试过了
dt_agg <- aggregate(. ~ Name,
data = dt,
FUN = f)
dt_agg您可以使用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)
您非常熟悉aggregate
函数,需要调整aggregate处理NA
的方式(从NA.ommit
到NA.pass
)。我的猜测是,aggregate首先删除带有NA的所有行,然后进行聚合,而不是在aggregate迭代要聚合的列时删除NAs。由于您的示例数据帧中的每一行都有一个NA
,最终得到的是一个0行数据帧(这是我在运行代码时遇到的错误)。我通过删除除一个NA之外的所有NA来测试这一点,并且您的代码按原样工作。所以我们设置na.action=na.pass
来传递na
dt_agg <- aggregate(. ~ Name,
data = dt,
FUN = f, na.action = "na.pass")
dt_agg如果在函数中添加一个ifelse()
,以确保函数在所有值均为NA
时返回一个值:
f <- function(x) {
x <- x[!is.na(x)]
ifelse(length(x) == 0, NA, x)
}
这将返回:
# 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
#一个tible:3 x 4
姓名身高体重年龄
1爱丽丝180 70 35
2 Bob NA 80 27
3查尔斯170 75纳
这里有一个带有数据的选项。表
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
只需在aggregate()中添加na.action=na.pass
call:
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
aggdf
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
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
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