[英]How to aggregate data in data.frame in R
我有一个很大的data.frame。 data.frame 包含很多值。
例如:
df <- data.frame(Company = c('A', 'A', 'B', 'C', 'A', 'B', 'B', 'C', 'C'),
Name = c("Wayne", "Duane", "William", "Rafael", "John", "Eric", "James", "Pablo", "Tammy"),
Age = c(26, 27, 28, 32, 28, 24, 34, 30, 25),
Wages = c(50000, 70000, 70000, 60000, 50000, 70000, 65000, 50000, 50000),
Education.University = c(1, 1, 1, 0, 0, 1, 1, 0, 1),
Productivity = c(100, 120, 120, 95, 88, 115, 100, 90, 120))
如何聚合我的data.frame
? 我想分析每家公司的价值观。 它必须看起来像:
年龄 -> 公司所有员工的平均年龄
工资 -> 公司所有员工的平均工资
Education.University -> 公司所有员工的因子总和(1 或 0)
生产力 -> 公司所有员工的平均生产力
基础R
cbind(aggregate(.~Company, df[,-c(2, 5)], mean),
aggregate(Education.University~Company, df, sum)[-1])
# Company Age Wages Productivity Education.University
#1 A 27.00000 56666.67 102.6667 2
#2 B 28.66667 68333.33 111.6667 3
#3 C 29.00000 53333.33 101.6667 1
这是更长的版本,可能更容易理解
merge(x = aggregate(x = list(Age_av = df$Age,
Wages_av = df$Wages,
Productivity_av = df$Productivity),
by = list(Company = df$Company),
FUN = mean),
y = aggregate(x = list(Education.University_sum = df$Education.University),
by = list(Company = df$Company),
FUN = sum),
by = "Company")
# Company Age_av Wages_av Productivity_av Education.University_sum
#1 A 27.00000 56666.67 102.6667 2
#2 B 28.66667 68333.33 111.6667 3
#3 C 29.00000 53333.33 101.6667 1
一种选择是使用data.table
library(data.table)
setDT(df)[, c(lapply(.SD[, c(2:3, 5), with = FALSE], mean),
.(Education.University = sum(Education.University))), by = Company]
# Company Age Wages Productivity Education.University
#1: A 27.00000 56666.67 102.6667 2
#2: B 28.66667 68333.33 111.6667 3
#3: C 29.00000 53333.33 101.6667 1
或者用dplyr
library(dplyr)
df %>%
group_by(Company) %>%
mutate(Education.University = sum(Education.University)) %>%
summarise_if(is.numeric, mean)
# A tibble: 3 x 5
# Company Age Wages Education.University Productivity
# <fctr> <dbl> <dbl> <dbl> <dbl>
#1 A 27.00000 56666.67 2 102.6667
#2 B 28.66667 68333.33 3 111.6667
#3 C 29.00000 53333.33 1 101.6667
您可以使用dplyr库轻松完成。
library(dplyr)
df %>% group_by(Company) %>% summarise(Age = mean(Age), Wages = mean(Wages), Education.University = sum(Education.University), Productivity = mean(Productivity))
已经发布的简洁data.table
解决方案是使用列号而不是列名。 根据有关 data.table 的常见问题解答,第 1.1 节,这被认为是不好的做法:
如果您的同事后来过来阅读您的代码,他们可能不得不四处寻找哪一列是第 5 列。如果您或他们更改了 R 程序中更高的列顺序,您可能会产生错误的结果,而不会发出警告或错误如果您忘记更改代码中引用第 5 列的所有位置。
所以,我想提出使用列名的替代方法。
library(data.table)
setDT(df)[, .(average.Age = mean(Age),
average.Wages = mean(Wages),
sum.Education.University = sum(Education.University),
average.Productivity = mean(Productivity)),
by = Company]
Company average.Age average.Wages sum.Education.University average.Productivity 1: A 27.00000 56666.67 2 102.6667 2: B 28.66667 68333.33 3 111.6667 3: C 29.00000 53333.33 1 101.6667
在这里,每一列都是单独聚合的。 虽然它需要更多的输入,但它有几个好处:
如果有很多列需要相同的操作, data.table
FAQ 建议使用.SDcols
。 所以,我们可以做
m_cols <- c("Age", "Wages", "Productivity")
s_cols <- c("Education.University")
by_cols <- c("Company")
setDT(df)[, c(.SD[, lapply(.SD, mean), .SDcols = m_cols],
.SD[, lapply(.SD, sum ), .SDcols = s_cols]),
by = by_cols]
Company Age Wages Productivity Education.University 1: A 27.00000 56666.67 102.6667 2 2: B 28.66667 68333.33 111.6667 3 3: C 29.00000 53333.33 101.6667 1
这类似于Akrun 的答案,但使用列名而不是列号。 此外,列名存储在一个便于编程的变量中。
请注意, by_cols
可能包含用于聚合的附加列,例如,
by_cols <- c("Company", "Name")
如果列顺序很重要,我们可以使用setcolorder()
:
result <- setDT(df)[, c(.SD[, lapply(.SD, mean), .SDcols = m_cols],
.SD[, lapply(.SD, sum ), .SDcols = s_cols]),
by = by_cols]
setcolorder(result, intersect(names(df), names(result)))
result
Company Age Wages Education.University Productivity 1: A 27.00000 56666.67 2 102.6667 2: B 28.66667 68333.33 3 111.6667 3: C 29.00000 53333.33 1 101.6667
同样,可以修改结果的列名以满足 OP 的要求:
setnames(result, m_cols, paste0("average.", m_cols))
setnames(result, s_cols, paste0("sum.", s_cols))
result
Company average.Age average.Wages sum.Education.University average.Productivity 1: A 27.00000 56666.67 2 102.6667 2: B 28.66667 68333.33 3 111.6667 3: C 29.00000 53333.33 1 101.6667
请注意, data.table
函数setcolorder()
和setnames()
就地工作,即不复制data.table
对象。 这可以节省内存和时间,这在处理大型表时尤为重要。
只需使用“聚合”功能
aggregate(x = df[c("Age","Wages","Education.University","Productivity")], by = df[c("Company")], FUN = mean)
# Company Age Wages Education.University Productivity
#1 A 27.00000 56666.67 0.6666667 102.6667
#2 B 28.66667 68333.33 1.0000000 111.6667
#3 C 29.00000 53333.33 0.3333333 101.6667
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.