簡體   English   中英

如何在R中的data.frame中聚合數據

[英]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 列的所有位置。

所以,我想提出使用列名的替代方法。

變體 1

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

在這里,每一列都是單獨聚合的。 雖然它需要更多的輸入,但它有幾個好處:

  1. 很容易理解代碼片段的目的。
  2. 結果中的列名可以根據需要修改。
  3. 如果需要,可以控制結果中列的順序。

變體 2

如果有很多列需​​要相同的操作, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM