将总和添加到tidyverse管道

时间:2019-05-24 08:50:47

标签: r

我正在使用:

library(tidyverse)

tips <- data.frame(
        gender = c("female", "male", "male")
        ,smoker = c("yes", "no", "no")
        , tip = c(10, 5, 0)
     )

tips %>%
    gather(key_value, value) %>% # wide to long
    count(key_value, value) %>%
    group_by(key_value) %>%
    mutate(percentage = round(n / sum(n), 2)) %>%
    unite(key_value_pair, key_value, value, sep = "=")

结果是:

  key_value_pair n percentage
1  gender=female 1       0.33
2    gender=male 2       0.67
3      smoker=no 2       0.67
4     smoker=yes 1       0.33
5          tip=0 1       0.33
6         tip=10 1       0.33
7          tip=5 1       0.33

在上面的示例中,是否有一种简单的方法求出列提示的总和,其中总和是特定组合的总和(例如,性别=女性,则有一行,因此总和为10,性别=男性,则有2行因此总和为5)。预期结果将是:

  key_value_pair n percentage sum
1  gender=female 1       0.33  10
2    gender=male 2       0.67   5
3      smoker=no 2       0.67   5
4     smoker=yes 1       0.33  10
5          tip=0 1       0.33   0
6         tip=10 1       0.33  10
7          tip=5 1       0.33   5

2 个答案:

答案 0 :(得分:2)

通过一些重新排列,仅需几行就可以准确获得所需的内容:

tips %>% 
    mutate(tip_sum = tip, n = 1) %>% 
    gather(column, value, -tip_sum, -n) %>%
    group_by(column, value) %>% 
    summarise_if(is.numeric, sum) %>% 
    mutate(perc = round(n/sum(n), 2))

#### OUTPUT ####

# A tibble: 7 x 5
# Groups:   column [3]
  column value  tip_sum     n  perc
  <chr>  <chr>    <dbl> <dbl> <dbl>
1 gender female      10     1  0.33
2 gender male         5     2  0.67
3 smoker no           5     2  0.67
4 smoker yes         10     1  0.33
5 tip    0            0     1  0.33
6 tip    10          10     1  0.33
7 tip    5            5     1  0.33

我唯一不包括的是unite,因为我认为它不是必不可少的。您可以根据需要将其添加回去。列顺序也有所不同。如果列顺序很重要,只需用select重新排列。

此解决方案也可以与其他数据很好地配合使用。例如,如果您的数据如下所示:

  gender smoker tip
1 female    yes  10
2   male     no   5
3   male     no   0
4 female     no   5
5   male    yes  10

上述解决方案将返回以下内容:

# A tibble: 7 x 5
# Groups:   column [3]
  column value  tip_sum     n  perc
  <chr>  <chr>    <dbl> <dbl> <dbl>
1 gender female      15     2   0.4
2 gender male        15     3   0.6
3 smoker no          10     3   0.6
4 smoker yes         20     2   0.4
5 tip    0            0     1   0.2
6 tip    10          20     2   0.4
7 tip    5           10     2   0.4

答案 1 :(得分:1)

诀窍是分别求和并合并,即

library(tidyverse)

tips <- data.frame(
        sex = c("female", "male", "male")
        , smoker = c("yes", "no", "no")
        , tip = c(10, 5, 0)
     )

tips %>%
     gather(key_value, value) %>% # wide to long
     count(key_value, value) %>%
     group_by(key_value) %>%
     mutate(percentage = round(n / sum(n), 2)) %>%
        left_join(
            tips %>%
            gather(key_value, value, - 'tip') %>%
            group_by(key_value, value) %>%
            summarise(s = sum(tip)),
            by = c('key_value', 'value')
        )

给出,

# A tibble: 7 x 5
# Groups:   key_value [?]
  key_value value      n percentage     s
  <chr>     <chr>  <int>      <dbl> <dbl>
1 gender    female     1       0.33    10
2 gender    male       2       0.67     5
3 smoker    no         2       0.67     5
4 smoker    yes        1       0.33    10
5 tip       0          1       0.33    NA
6 tip       10         1       0.33    NA
7 tip       5          1       0.33    NA

如果您确实需要用与key_value相同的值填充tip的NA,则可以轻松地替换它们(或coalesce),等等。