【问题标题】:Computing weighted marginal averages in a table with addmargin使用 addmargin 计算表中的加权边际平均值
【发布时间】:2021-04-10 17:50:48
【问题描述】:

我创建了一个表格,其中包含人们参与按国家和性别划分的调查的平均天数。

   tbl_tmp <- df_tmp1 %>% 
                 group_by(country, Sex) %>%      
                 summarize(Mean_Days_Used = round(mean(Days_Used), 1)) %>% 
                 spread(Sex, Mean_Days_Used) 

结果是

# A tibble: 10 x 4
# Groups:   country [10]
   country Female     Male       `No Response`
   <chr>   <drtn>     <drtn>     <drtn>       
 1 AU       23.3 days    NA days NA days      
 2 CA       60.8 days  46.5 days NA days      
 3 FR         NA days  17.0 days NA days      
 4 GB       52.0 days  62.8 days 31 days      
 5 HK         NA days 125.0 days NA days      
 6 IE      109.6 days 100.5 days NA days      
 7 JP         NA days  10.0 days NA days      
 8 NZ      118.0 days   8.0 days NA days      
 9 PL         NA days    NA days 27 days      
10 US       35.2 days  41.7 days 86 days 

我现在想为每一行和每一列添加边际平均值,但有两个转折:

  1. 我想要一个加权平均值(按每个单元格中条目的比例加权),而不仅仅是一个简单的行或列平均值
  2. 我需要处理 NA,当没有来自特定国家的特定性别的受访者时会出现这种情况

我通常会使用addmargins 来添加所有边际总和/平均值等,但这无法解释每个单元格中进入者的相对频率,此外,还会阻塞 NA。例如,如果新西兰有 10 名男性受访者和 20 名女性受访者,我希望边缘列的第 8 行为 (118 * 10 + 8 * 20 + 0 )/30 = 44.67。类似的论点适用于加权列均值。

我应该如何计算这些加权平均值?

在此致以诚挚的谢意

托马斯·飞利浦

【问题讨论】:

  • 在您总结之前,如果您可以为df_tmp1 提供dput 会有所帮助。或者至少是 dput 的一个子集,其中包含几个国家/地区的价值数据。
  • df_tmp1 &lt;- tibble( UserId = LETTERS[1:11], country = c(rep("AU", 5), rep("CA", 6)), Sex = c(rep("Female", 3), rep("Male", 2), "Female", rep("Male", 2), rep("No Response", 3) ), Days_Used = 1:11 )
  • 你如何计算边缘列? (Average_Female_days * count_of_male + Average_male_days * count_of_female + Average_No_Response)/Total_count_of_country ?
  • 在任何给定的行(即对于任何给定的国家),我想计算(Average_Female_days_in_this_country * count_of_female_in_this_country + Average_male_days_in_this_country * count_of_male_in_this_country + Average_No_Response_days_in_this_country * count_of_No_Response_in_this_country)/Total_count_in_this_country。以此类推,每列底部的平均值是给定性别的受访者平均天数在所有国家/地区的加权平均值

标签: r dplyr datatable


【解决方案1】:

您可以尝试使用:

library(dplyr)
library(tidyr)

df_tmp1 %>% 
  group_by(country, Sex) %>%      
  summarise(Mean_Days_Used = mean(Days_Used),
            n = n()) %>%
  mutate(total = (Mean_Days_Used * n)/sum(n)) %>%
  ungroup %>%
  select(-n, -Mean_Days_Used) %>%
  pivot_wider(names_from = Sex, values_from = total) %>%
  mutate(mean = rowMeans(.[-1], na.rm = TRUE)) -> df1


result <- rbind(df1, data.frame(country = 'Total', 
                     t(colMeans(df1[-1], na.rm = TRUE)), check.names = FALSE))

【讨论】:

  • 这是朝着正确的方向前进,但并不完全存在,因为它不是表格格式。每个国家需要 1 行,每个性别需要 1 列。总数在下方和右侧。我想我可以删除列 n', and keep total`,但我仍然缺少列摘要
  • 我已更新答案以在数据中添加行/列摘要。 @ThomasPhilips
  • 这很有效,而且比我笨拙的解决方案更紧凑。谢谢。
【解决方案2】:

我有一个笨拙的答案,但肯定有一个更干净的方法

   Avg_by_Bucket <- df_tmp1 %>%
                       group_by(country,Sex)%>%
                       summarize(Mean_Days_Used = round(mean(Days_Used), 1))%>%
                       spread(Sex, Mean_Days_Used)
    
    Avg_by_country <- df_tmp1 %>%
                        group_by(country)%>%
                        summarize(Mean_Days_Used = round(mean(Days_Used), 1))
    
    Avg_by_Sex <- df_tmp1 %>%
                    group_by(Sex)%>%
                    summarize(Mean_days_used_by_sex = round(mean(Days_Used), 1))%>%
                    spread(Sex, Mean_days_used_by_sex)
    
    Overall_Avg <- df_tmp1 %>%
                      summarize(Mean_Days_Used = round(mean(Days_Used), 1))
    
df_tmp_a <- full_join(Avg_by_Bucket, Avg_by_country, by = 'country')
df_tmp_b <- bind_cols(Avg_by_Sex, Overall_Avg)

table_3  <- bind_rows(df_tmp_a, df_tmp_b)
table_3[dim(table_3)[1], 1] <- "Mean_Days_Used"
column_to_rownames(table_3, var = "country")

当应用于我的玩具数据集时

> df_tmp1
# A tibble: 11 x 4
   UserId country Sex         Days_Used
   <chr>  <chr>   <chr>           <int>
 1 A      AU      Female              1
 2 B      AU      Female              2
 3 C      AU      Female              3
 4 D      AU      Male                4
 5 E      AU      Male                5
 6 F      CA      Female              6
 7 G      CA      Male                7
 8 H      CA      Male                8
 9 I      CA      No Response         9
10 J      CA      No Response        10
11 K      CA      No Response        11

使用

生成
df_tmp1 <- tibble(
                  UserId = LETTERS[1:11],
                  country = c(rep("AU", 5), rep("CA", 6)),
                  Sex = c(rep("Female", 3), rep("Male", 2), "Female", rep("Male", 2), rep("No Response", 3) ),                              
                  Days_Used = 1:11
                  )

给我我想要的:

               Female Male No Response Mean_Days_Used
AU                  2  4.5          NA            3.0
CA                  6  7.5          10            8.5
Mean_Days_Used      3  6.0          10            6.0

【讨论】:

    猜你喜欢
    • 2011-02-12
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    • 2021-11-21
    • 2017-04-22
    相关资源
    最近更新 更多