创建 Dataframe w/All 2 个分类列的组合,然后按每个组合对第 3 列求和

Create Dataframe w/All Combinations of 2 Categorical Columns then Sum 3rd Column by Each Combination

我有一个很大的杂乱数据集,但想完成一件简单的事情。本质上,我想根据两列的每个组合来填充小标题并对第三列求和。

作为一个假设的例子,假设每个观察结果有 company_name(Wendys、BK、麦当劳)、food_option(汉堡、薯条、冰霜)和 total_spending(美元)。我想用公司、食物和总计做一个 9x3 tibble 作为每个观察的总和。到目前为止,这是我的代码:

df_table <- df %>% 
      group_by(company_name, food_option) %>%
      summarize(total= sum(total_spending))
 company_name                food_option               total
   <chr>                     <chr>                      <dbl>
 1 Wendys                    Burgers                   757
 2 Wendys                    Fries                     140
 3 Wendys                    Frosty                    98
 4 McDonalds                 Burgers                   1044
 5 McDonalds                 Fries                     148
 6 BK                        Burgers                   669
 7 BK                        Fries                     38

问题是麦当劳的 "Frosty" 作为 food_option 的观测值为零。因此,我得到了部分 table。我想用显示的行填充它:

 8  McDonalds      Frosty   0 
 9  BK             Frosty   0

我知道我可以手动添加行,但实际的数据集有一百多种组合,所以会很繁琐和复杂。另外,我一直在修改上游数据,我希望代码能够自动正确填充。

非常感谢任何能提供帮助的人。这个论坛真的是天赐之物,真的很感谢你们所有人。

您可以使用 tidyr::expand_grid():

tidyr::expand_grid(company_name = c("Wendys", "McDonalds", "BK"), 
                   food_option = c("Burgers", "Fries", "Frosty"))

创建所有可能的变体

尝试:

library(dplyr)

df %>% 
  mutate(food_option = factor(food_option, levels = unique(food_option))) %>% 
  group_by(company_name, food_option, .drop = FALSE) %>% 
  summarise(total = sum(total_spending))

dplyr 的较新版本对 group_by 有一个 .drop 参数,如果你有一个具有预定义级别的因子,它们将不会被删除(而且你会得到零)。

library(tidyverse)

# example data
df = read.table(text = "
company_name                food_option               total
1 Wendys                    Burgers                   757
2 Wendys                    Fries                     140
3 Wendys                    Frosty                    98
4 McDonalds                 Burgers                   1044
5 McDonalds                 Fries                     148
6 BK                        Burgers                   669
7 BK                        Fries                     38
", header=T)

df %>% complete(company_name, food_option, fill=list(total = 0))

# # A tibble: 9 x 3
#   company_name food_option total
#   <fct>        <fct>       <dbl>
# 1 BK           Burgers       669
# 2 BK           Fries          38
# 3 BK           Frosty          0
# 4 McDonalds    Burgers      1044
# 5 McDonalds    Fries         148
# 6 McDonalds    Frosty          0
# 7 Wendys       Burgers       757
# 8 Wendys       Fries         140
# 9 Wendys       Frosty         98