后续:重新排序一个对称的tibble

Follow-up: Re-ordering a symmetric tibble

我正在跟进 。特别是,我想知道如何将输出的第一列值(实际上是行名)与其余列名一起重新排序?

我被建议 但是这两个解决方案似乎在函数中不起作用。这个问题有 tidyverse 解决方案吗?

foo <- function(data, study_id, ...){
  
   study_id <- rlang::ensym(study_id)
   cat_mod <- rlang::ensyms(...)
   purrr::map(cat_mod,  ~ {
  
   studies_cats <- 
     data %>%
     dplyr::group_by(!!study_id, !!.x) %>%
     dplyr::summarise(effects = n(), .groups = 'drop')
     nm1 <- rlang::as_string(.x)
     cat_names <- paste0(nm1, c(".x", ".y"))
    studies_cats <- 
      studies_cats %>%
      dplyr::inner_join(studies_cats, by = rlang::as_string(study_id)) %>%
      dplyr::group_by(!!!rlang::syms(cat_names)) %>%
      dplyr::summarise(
        studies = n(),
        effects = sum(effects.x), .groups = 'drop') %>% 
      dplyr::mutate(n = paste0(studies, " (", effects, ")") )

    studies_cats %>%
      dplyr::select(-studies, -effects) %>%
      tidyr::pivot_wider(names_from = cat_names[2], values_from = n) %>%
      dplyr::rename_with(~nm1,  cat_names[1]) })}

# EXAMPLE OF USE (notice columnames are ordered `0,1,10,2,3` but 
# first column values are ordered: `0,1,2,3,10`):

d <- read.csv("https://raw.githubusercontent.com/rnorouzian/s/main/w7_smd_raw.csv")
foo(data, study, error.type)

#  error.type `0`      `1`      `10`   `2`    `3`   
#  <fct>      <chr>    <chr>    <chr>  <chr>  <chr> 
#1 0          27 (189) 1 (6)    1 (2)  NA     NA    
#2 1          1 (18)   16 (118) 2 (10) 2 (6)  2 (6) 
#3 2          NA       2 (6)    NA     6 (33) 2 (6) 
#4 3          NA       2 (6)    NA     2 (6)  5 (27)
#5 10         1 (2)    2 (22)   6 (48) NA     NA   

pivot_wider 创建列顺序的行为基于 unique 默认指定的 names_to 列值的相同顺序(因为 names_sort = FALSE ).如果我们想让顺序动态化,那么一个选择是先 arrange 列(这是数字)。执行 arrange 也使事情变得更加灵活,即假设我们只想基于子字符串(即数字部分)进行排序,可以提取这些并执行排序,而在 names_sort 中可能并非如此

foo <- function(data, study_id, ...){
  
     study_id <- rlang::ensym(study_id)
     cat_mod <- rlang::ensyms(...)
     purrr::map(cat_mod,  ~ {
  
     studies_cats <- 
       data %>%
       dplyr::group_by(!!study_id, !!.x) %>%
       dplyr::summarise(effects = n(), .groups = 'drop')
       nm1 <- rlang::as_string(.x)
       cat_names <- paste0(nm1, c(".x", ".y"))
      studies_cats <- 
        studies_cats %>%
        dplyr::inner_join(studies_cats, by = rlang::as_string(study_id)) %>%
        dplyr::group_by(!!!rlang::syms(cat_names)) %>%
        dplyr::summarise(
          studies = n(),
          effects = sum(effects.x), .groups = 'drop') %>% 
        dplyr::mutate(n = paste0(studies, " (", effects, ")") )

      studies_cats %>%
        dplyr::select(-studies, -effects) %>%
        dplyr::arrange(across(all_of(cat_names[2]))) %>%
        tidyr::pivot_wider(names_from = cat_names[2], values_from = n) %>%
        dplyr::rename_with(~nm1,  cat_names[1])  %>%
        dplyr::arrange(across(all_of(nm1))) %>%
        dplyr::mutate(across(all_of(nm1), as.character))
        
          })
        }

-输出

foo(d, study, error.type)
[[1]]
# A tibble: 5 x 6
  error.type `0`      `1`      `2`    `3`    `10`  
  <chr>      <chr>    <chr>    <chr>  <chr>  <chr> 
1 0          27 (189) 1 (6)    <NA>   <NA>   1 (2) 
2 1          1 (18)   16 (118) 2 (6)  2 (6)  2 (10)
3 2          <NA>     2 (6)    6 (33) 2 (6)  <NA>  
4 3          <NA>     2 (6)    2 (6)  5 (27) <NA>  
5 10         1 (2)    2 (22)   <NA>   <NA>   6 (48)

或者也可以使用names_sort = TRUE

foo <- function(data, study_id, ...){
  
       study_id <- rlang::ensym(study_id)
       cat_mod <- rlang::ensyms(...)
       purrr::map(cat_mod,  ~ {
  
       studies_cats <- 
         data %>%
         dplyr::group_by(!!study_id, !!.x) %>%
         dplyr::summarise(effects = n(), .groups = 'drop')
         nm1 <- rlang::as_string(.x)
         cat_names <- paste0(nm1, c(".x", ".y"))
        studies_cats <- 
          studies_cats %>%
          dplyr::inner_join(studies_cats, by = rlang::as_string(study_id)) %>%
          dplyr::group_by(!!!rlang::syms(cat_names)) %>%
          dplyr::summarise(
            studies = n(),
            effects = sum(effects.x), .groups = 'drop') %>% 
          dplyr::mutate(n = paste0(studies, " (", effects, ")") )

        studies_cats %>%
          dplyr::select(-studies, -effects) %>%        
          tidyr::pivot_wider(names_from = cat_names[2], 
                values_from = n, names_sort = TRUE) %>%
          dplyr::rename_with(~nm1,  cat_names[1])  %>%
          dplyr::arrange(across(all_of(nm1))) %>%
          dplyr::mutate(across(all_of(nm1), as.character))
        
            })
          }

-输出

> foo(d, study, error.type)
[[1]]
# A tibble: 5 x 6
  error.type `0`      `1`      `2`    `3`    `10`  
  <chr>      <chr>    <chr>    <chr>  <chr>  <chr> 
1 0          27 (189) 1 (6)    <NA>   <NA>   1 (2) 
2 1          1 (18)   16 (118) 2 (6)  2 (6)  2 (10)
3 2          <NA>     2 (6)    6 (33) 2 (6)  <NA>  
4 3          <NA>     2 (6)    2 (6)  5 (27) <NA>  
5 10         1 (2)    2 (22)   <NA>   <NA>   6 (48)