【问题标题】:Adding overall mean when using group_by使用 group_by 时添加总体平均值
【发布时间】:2018-10-25 05:25:36
【问题描述】:

我正在使用 dplyr 包生成一些表,并且我正在使用 adorn_totals("row") 函数。

当我想对组内的值求和时,这很好用,但在某些情况下,我想要一个整体平均值而不是总和。有adorn_means函数吗?

示例代码:

Regions2 <- Data %>%
  filter(!is.na(REGION))%>%
  group_by(REGION) %>%
  summarise(Numberofpeople=length(Names))%>%
  adorn_totals("row")

这里我的“总”行只是区域内所有人的总和。这给了我

REGION          NumberofPeople
East Midlands       578,943
East of England     682,917
London            1,247,540
North East          245,830
North West          742,886
South East          963,040
South West          623,684
West Midlands       653,335
Yorkshire           553,853
TOTAL             6,292,028

我的下一段代码会生成每个地区的平均工资,但我想为总数添加一个总体平均值

Regions3 <- Data %>%
  filter(!is.na(REGION))%>%
  filter(!is.na(AVGSalary))%>%
  group_by(REGION) %>%
  summarise(AverageSalary=mean(AVGSalary))

如果我像以前一样使用adnorn_totals("row"),我只会得到平均值的总和,而不是数据集的整体平均值。

如何获得总体平均值?

更新一些点头数据:

数据

people  region      salary
person1 London      1000
person2 South West  1050
person3 South East  900
person4 London      800
person5 Scotland    1020
person6 South West  750
person7 East        600
person8 London      1200
person9 South West  1150

因此,组平均值为:

London      1000
South West  983.33
South East  900
Scotland    1020
East        600

我想把总数加到底部

Total    941.11

【问题讨论】:

  • 请提供Data 的一个可重复的小例子。 'AVGSalary' 列不在显示的输出中。你是说想要mean而不考虑TOTAL
  • 如果你想绕过group_by,整列使用.data$AVGSalary$AVGSalary
  • 我不想绕过 group_by - 我需要按组(在本例中为区域)进行细分。我需要在组的底部显示整个数据集的 AVGSalary
  • 你的意思是Data %&gt;% group_by(region) %&gt;% summarise(Avgsalary = mean(salary)) %&gt;% bind_rows(., data_frame(region = 'Total', Avgsalary = mean(.$Avgsalary)))

标签: r dplyr


【解决方案1】:

1) 因为总体平均值是平均值的加权平均值(不是平均值的普通平均值),即它是 941 而不是 901,所以我们维护一个 n 列,以便最后,我们可以正确计算总体平均值。尽管显示的数据没有任何 NA,但我们使用 drop_na 以便也将其与此类数据一起使用。这将删除任何包含 NA 的行。

library(dplyr)
library(tidyr)

Region %>%
  drop_na %>%
  group_by(region) %>%
  summarize(avg = mean(salary), n = n()) %>%
  ungroup %>%
  bind_rows(summarize(., region = "Overall Avg", 
                         avg = sum(avg * n) / sum(n), 
                         n = sum(n))) %>%
  select(-n)

给予:

# A tibble: 6 x 2
  region        avg
  <chr>       <dbl>
1 East         600 
2 London      1000 
3 Scotland    1020 
4 South East   900 
5 South West   983.
6 Overall Avg  941.

2) 另一种方法是通过返回原始数据来构建总体平均线:

Region %>%
  drop_na %>%
  group_by(region) %>%
  summarize(avg = mean(salary)) %>%
  ungroup %>%
  bind_rows(summarize(Region %>% drop_na, region = "Overall Avg", avg = mean(salary)))

给予:

# A tibble: 6 x 2
  region        avg
  <chr>       <dbl>
1 East         600 
2 London      1000 
3 Scotland    1020 
4 South East   900 
5 South West   983.
6 Overall Avg  941.

2a) 如果您反对两次提及Region,那么试试这个。

Region_ <- Region %>% 
  drop_na

Region_ %>%
  group_by(region) %>%
  summarize(avg = mean(salary)) %>%
  ungroup %>%
  bind_rows(summarize(Region_, region = "Overall Avg", avg = mean(salary)))

2b) 或作为单个管道,现在Region_ 是管道本地的,并且将在管道完成后自动删除:

Region %>%
  drop_na %>%
  { Region_ <- .
    Region_ %>%
      group_by(region) %>%
      summarize(avg = mean(salary)) %>%
      ungroup %>%
      bind_rows(summarize(Region_, region = "Overall Avg", avg = mean(salary)))
  }

注意

我们用这个作为输入:

Lines <- "people  region      salary
person1 London      1000
person2 South West  1050
person3 South East  900
person4 London      800
person5 Scotland    1020
person6 South West  750
person7 East        600
person8 London      1200
person9 South West  1150"

library(gsubfn)
Region <- read.pattern(text = Lines, pattern = "^(\\S+) +(.*) (\\d+)$", 
  as.is = TRUE, skip = 1, strip.white = TRUE,
  col.names = read.table(text = Lines, nrow = 1, as.is = TRUE))

【讨论】:

    【解决方案2】:

    一个选项是添加一行bind_rows

    library(dplyr)
    Data %>% 
       group_by(region) %>% 
       summarise(Avgsalary = mean(salary)) %>%
       bind_rows(data_frame(region = 'Total',
                            Avgsalary = mean(.$Avgsalary, na.rm = TRUE)))
    

    或者另一个选项是来自tibbleadd_row

    Data %>% 
       group_by(region) %>% 
       summarise(Avgsalary = mean(salary)) %>% 
       add_row(region = 'Total', Avgsalary = mean(.$Avgsalary))
    

    如果这是基于取mean之前的总体平均值,那么我们需要在之前计算它

    Data %>%  
      mutate(Total = mean(salary)) %>% 
      group_by(region) %>%
      summarise(Avgsummary = mean(salary), Total = first(Total)) %>% 
      add_row(region = 'Total', Avgsummary = .$Total[1]) %>% 
      select(-Total)
    

    【讨论】:

    • 这不起作用 - 我怀疑 Avgsalary 变量中有一些 NA 值。在管道中,我使用了 nas 过滤器,但它不适用于 bind_rows。
    • @Nottles82 添加mean(.$Avgsalary, na.rm = TRUE)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    相关资源
    最近更新 更多