R:找到每个组内和整个数据帧内的相对权重

R: find relative weight within each group and within the entire dataframe

我的数据框在每一行中都有一个值,其中包含另外两个变量。

library(tidyverse)
df <- data_frame( car=c('A','A','A','B','B'), style=c('aa','bb','aa','aa','cc'), value=c(3,2,5,4,16) )

 car  style   value
 A     aa      3
 A     bb      2
 A     aa      5
 B     aa      4
 B     cc      16

如何找到每个车组中每种风格的相对权重,以及每种风格在所有数据中的相对权重?这是所需的输出(不需要右侧的 # 注释,但为了清楚显示总重量计算而在此处添加):

 car  style   value  style_for_car   style_total     # total value count is 30
 A     aa      3         0.80            0.40         # (3+5+4)/30 = 0.40
 A     bb      2         0.20            0.067        # 2/30 = 0.067            
 A     aa      5         0.80            0.40          
 B     aa      4         0.20            0.40
 B     cc     16         0.80            0.533

我下面的尝试只成功计算了总重量。如何在同一个 dplyr 管道中获得所需的输出:

df %>%
    group_by(style) %>%
    mutate( style_total = sum(value)/sum(.$value) )

     car  style   value   style_total
       A    aa     3       0.4000
       A    bb     2       0.0667
       A    aa     5       0.4000
       B    aa     4       0.4000
       B    cc    16       0.5333

原始答案 - 基于原始问题编号

一些额外的行应该这样做 group_by(car)mutate() 来计算 style_for_car ...

df %>%
  group_by(car) %>%
  mutate(style_for_car = value / sum(value)) %>% 
  group_by(style) %>%
  mutate( style_total = sum(value) / sum(.$value)) 

#> Source: local data frame [5 x 5]
#> Groups: style [3]
#> 
#>     car style value style_for_car style_total
#>   <chr> <chr> <dbl>         <dbl>       <dbl>
#> 1     A    aa     3           0.3  0.40000000
#> 2     A    bb     2           0.2  0.06666667
#> 3     A    aa     5           0.5  0.40000000
#> 4     B    aa     4           0.2  0.40000000
#> 5     B    cc    16           0.8  0.53333333

更新的答案 - 基于更新的问题编号和关于 .$

的评论

@alistaire 在评论中提出了一个不错的单管道解决方案。要添加,我倾向于创建包含相关信息的单独数据框,然后将它们加入原始数据框。这使代码更具可读性(至少对我而言)。这是我的处理方式(也摆脱了 .$):

# Create values for style_for_cars
df_cars <- df %>% 
             group_by(car, style) %>% 
             summarise(value = sum(value)) %>% 
             group_by(car) %>% 
             mutate(style_for_car = value / sum(value)) %>% 
             select(-value)
df_cars
#> Source: local data frame [4 x 3]
#> Groups: car [2]
#> 
#>     car style style_for_car
#>   <chr> <chr>         <dbl>
#> 1     A    aa           0.8
#> 2     A    bb           0.2
#> 3     B    aa           0.2
#> 4     B    cc           0.8

# Create values for style_total
df_total <- df %>%
              group_by(style) %>% 
              summarise(value = sum(value)) %>% 
              mutate(style_total = value / sum(value)) %>% 
              select(-value)
df_total
#> # A tibble: 3 × 2
#>   style style_total
#>   <chr>       <dbl>
#> 1    aa  0.40000000
#> 2    bb  0.06666667
#> 3    cc  0.53333333

# Join results
df %>%
  left_join(df_cars) %>% 
  left_join(df_total)
#> Joining, by = c("car", "style")
#> Joining, by = "style"
#> # A tibble: 5 × 5
#>     car style value style_for_car style_total
#>   <chr> <chr> <dbl>         <dbl>       <dbl>
#> 1     A    aa     3           0.8  0.40000000
#> 2     A    bb     2           0.2  0.06666667
#> 3     A    aa     5           0.8  0.40000000
#> 4     B    aa     4           0.2  0.40000000
#> 5     B    cc    16           0.8  0.53333333