繁体   English   中英

是否可以使用 pivot 规格来完成异构 pivot_wider?

[英]Can a heterogenous pivot_wider be done using pivot specs?

某些“异构”枢轴可以通过连接多个更简单的枢轴来实现。 pivot 规格是否允许这些发生在一个 go 中? 例如,假设您有以下数据:

library(dplyr)
library(tidyr)

set.seed(123)

Z <- tibble(id = rep(1:3, 2:4),
            x = runif(length(id)),
            month = sample(month.abb, length(id)))

假设对于每个id您想要对其x求和,然后通过每月 true/false 列报告这些x在哪些月份发生。 您可以使用两个枢轴按如下方式进行:

Z |> 
  mutate(name = 'x') ->
  Z1

Z |> 
  mutate(value = TRUE) ->
  Z2

inner_join(
  Z1 |> pivot_wider(id_cols = id, values_from = x, values_fn = sum), # alternatively group_by & summarize
  Z2 |> pivot_wider(id_cols = id, names_from = month, values_fill = FALSE),
  by = 'id') ->
  desired_result

上面使用 pivot 规格(并且仍然使用两个枢轴)的变体是:

Z1 |> 
  build_wider_spec(values_from = x) ->
  spec1

Z2 |> 
  build_wider_spec(names_from = month) ->
  spec2

inner_join(
  Z1 |> pivot_wider_spec(spec1, id_cols = id, values_fn = sum),
  Z2 |> pivot_wider_spec(spec2, id_cols = id, values_fill = FALSE),
  by = 'id') ->
  desired_result2

stopifnot(identical(desired_result, desired_result2))

我的问题是使用 pivot 规格是否可以通过单个 pivot 来完成。我的想法是:

# Does not work
Z |> 
  mutate(name = 'x', value = TRUE) |> 
  pivot_wider_spec(bind_rows(spec1, spec2), id_cols = id, values_fn = list(x = sum))

虽然上面不起作用。

(FWIW,我怀疑以上内容不起作用,因为bind_rows(spec1, spec2)包含NA s;更一般地说,我怀疑pivot_wider不是为了涵盖这种情况而设计的;但是我认为值得请教专家。)

在这里,我们不需要两个pivot_wider 相反,它可以通过创建一个新的 sum 列来完成,然后通过使用values_fnpivot_wider做一次values_fill

library(dplyr)
library(tidyr)
Z %>%
   group_by(id) %>% 
   mutate(x1 = x, x = sum(x)) %>%
   ungroup %>% 
   pivot_wider(names_from = month, values_from = x1, 
         values_fn = ~ TRUE, values_fill = FALSE)

-输出

# A tibble: 3 × 11
     id     x May   Apr   Jun   Sep   Feb   Mar   Dec   Jul   Oct  
  <int> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
1     1  1.08 TRUE  TRUE  FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2     2  2.23 FALSE FALSE TRUE  TRUE  TRUE  FALSE FALSE FALSE FALSE
3     3  2.02 FALSE FALSE FALSE FALSE FALSE TRUE  TRUE  TRUE  TRUE 

-OP 的 output

> desired_result
# A tibble: 3 × 11
     id     x May   Apr   Jun   Sep   Feb   Mar   Dec   Jul   Oct  
  <int> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
1     1  1.08 TRUE  TRUE  FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2     2  2.23 FALSE FALSE TRUE  TRUE  TRUE  FALSE FALSE FALSE FALSE
3     3  2.02 FALSE FALSE FALSE FALSE FALSE TRUE  TRUE  TRUE  TRUE 

编辑:基于@banbh 评论

也许不是 100% 你的想法,但使用一个mutate步骤和 pivot_wider 的id_colsunused_fn pivot_wider你可以做到:

library(dplyr, warn=FALSE)
library(tidyr)

Z |>
  mutate(value = TRUE) |>
  pivot_wider(
    id_cols = id, names_from = month, values_from = value,
    unused_fn = sum, values_fill = FALSE
  )
#> # A tibble: 3 × 11
#>      id May   Apr   Jun   Sep   Feb   Mar   Dec   Jul   Oct       x
#>   <int> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <dbl>
#> 1     1 TRUE  TRUE  FALSE FALSE FALSE FALSE FALSE FALSE FALSE  1.08
#> 2     2 FALSE FALSE TRUE  TRUE  TRUE  FALSE FALSE FALSE FALSE  2.23
#> 3     3 FALSE FALSE FALSE FALSE FALSE TRUE  TRUE  TRUE  TRUE   2.02

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM