【问题标题】:Sequential aggregation with a single call of pivot_wider单次调用 pivot_wider 的顺序聚合
【发布时间】:2022-01-14 18:54:27
【问题描述】:

考虑数据框:

df <- data.frame(x = c(1,2,1,1), y = c("a", "a", "b", "a"))

通过应用下面的代码

library(tidyverse)

df %>% 
  pivot_wider(x, names_from = y, values_from = y, values_fn = length, names_prefix = "tot_", values_fill = 0) %>% 
  mutate(per_a = 100*tot_a / rowSums(select(.,starts_with("tot_")))) %>% 
  mutate(per_b = 100*tot_b / rowSums(select(.,starts_with("tot_"))))

一个人得到结果

   <dbl> <int> <int> <dbl> <dbl>
 1     1     2     1  66.7  33.3
 2     2     1     0 100     0

我的问题是:是否有可能使用pivot_wider单个 调用获得相同的结果,也就是说,没有任何mutate

【问题讨论】:

  • proportions(table(df), 1)*100 呢?
  • 谢谢,@Onyambu。但是,我的问题的动机是找出是否可以通过使用单个pivot_wider 来完成这样的结果。
  • 我不这么认为。 value_fn 是一个聚合函数,因此在这种情况下不符合条件。可能只有一个 mutate 调用
  • 文档说value_fn可以是函数列表,@Onyambu。
  • 是的,所有聚合。即他们按组工作并给出统一/单一的结果。在您的情况下,您有 a 组和 b 组,它们是依赖的,因为 66.7 是通过在除法之前计算 a AND B 中的所有值而获得的。

标签: r tidyverse tidyr


【解决方案1】:

你需要group_by 两次我想如果你想在没有mutate 的情况下对每个percentage 列分别执行一次pivot_wider

df %>%
  group_by(x,y) %>%
  count(name="tot") %>%
  group_by(x) %>%
  mutate(per = tot / sum(tot)) %>%
  pivot_wider(id_cols = x, names_from=y, values_from=c(tot,per))

## A tibble: 2 x 5
## Groups:   x [2]
#      x tot_a tot_b per_a  per_b
#  <dbl> <int> <int> <dbl>  <dbl>
#1     1     2     1 0.667  0.333
#2     2     1    NA 1     NA   

这对我来说很“整洁”,因为您在长格式、整洁的数据中进行 2 次分组扫描中的所有计算,而不是尝试手动选择宽格式的多个列。

【讨论】:

    【解决方案2】:

    其他解决方案选项

    data.table

    df <- data.frame(x = c(1,2,1,1), y = c("a", "a", "b", "a"))
    
    library(data.table)
    library(magrittr)
    setDT(df)[, list(tot = .N), by = list(x, y)] %>% 
      .[, perc := proportions(tot), by = list(y)] %>% 
      dcast(x ~ y, value.var = c("tot", "perc"), fill = 0)
    #>    x tot_a tot_b    perc_a perc_b
    #> 1: 1     2     1 0.6666667      1
    #> 2: 2     1     0 0.3333333      0
    

    reprex package (v2.0.1) 于 2021 年 12 月 10 日创建

    tidyverse

    library(tidyverse)
    df <- data.frame(x = c(1,2,1,1), y = c("a", "a", "b", "a"))
    
    df %>%
      pivot_wider(
        x,
        names_from = y,
        values_from = y,
        values_fn = length,
        names_prefix = "tot_",
        values_fill = 0
      ) %>% 
      mutate(across(starts_with("tot_"), proportions, .names = "{.col}_prop"))
    #> # A tibble: 2 x 5
    #>       x tot_a tot_b tot_a_prop tot_b_prop
    #>   <dbl> <int> <int>      <dbl>      <dbl>
    #> 1     1     2     1      0.667          1
    #> 2     2     1     0      0.333          0
    

    reprex package (v2.0.1) 于 2021-12-10 创建

    【讨论】:

      猜你喜欢
      • 2020-01-30
      • 1970-01-01
      • 1970-01-01
      • 2014-05-25
      • 1970-01-01
      • 2016-03-20
      • 2021-02-24
      • 2017-03-24
      • 1970-01-01
      相关资源
      最近更新 更多