【问题标题】:how to create a list column of column names where column values are TRUE如何创建列值为 TRUE 的列名的列表列
【发布时间】:2021-02-17 22:20:52
【问题描述】:

我有一些关于多项选择问题的调查数据,这些数据已经输出,每个可能的选择都有一列,填充有 TRUE/FALSE 值,例如

library(dplyr)

dat <- tribble(
  ~name, ~state, ~onions, ~`sweet potatoes`, ~garlic,
  "Tom", "WV", TRUE, FALSE, TRUE,
  "Larry", "NC", FALSE, TRUE, FALSE,
  "Beth", "NY", TRUE, TRUE, TRUE
)

dat

#>   name  state onions `sweet potatoes` garlic
#>   <chr> <chr> <lgl>  <lgl>            <lgl> 
#> 1 Tom   WV    TRUE   FALSE            TRUE  
#> 2 Larry NC    FALSE  TRUE             FALSE 
#> 3 Beth  NY    TRUE   TRUE             TRUE  

如何创建一个列表列,其中包含受访者回答“真”的列名?

类似于https://stackoverflow.com/a/9508203/1009730

我尝试了多种主题的变体

dat %>%
  rowwise() %>%
  mutate(fav_foods = list(names(which(~ is.logical(.x) && .x))))

给出错误:

错误:mutate() 输入 fav_foods 有问题。 'which' 的 x 参数不符合逻辑 i 输入 fav_foodslist(names(which(~is.logical(.x) &amp;&amp; .x)))。 i 错误发生在第 1 行。

【问题讨论】:

  • 我更喜欢新专栏,所以我猜mutate 可能会比summarise 更好。编辑问题以反映这一点。

标签: r dplyr


【解决方案1】:

加上purrr,你可以这样做:

dat %>%
 mutate(fav_foods = pmap_chr(across(where(is.logical)), ~ toString(names(c(...))[which(c(...))])))

  name  state onions `sweet potatoes` garlic fav_foods                     
  <chr> <chr> <lgl>  <lgl>            <lgl>  <chr>                         
1 Tom   WV    TRUE   FALSE            TRUE   onions, garlic                
2 Larry NC    FALSE  TRUE             FALSE  sweet potatoes                
3 Beth  NY    TRUE   TRUE             TRUE   onions, sweet potatoes, garlic

或者如果你需要它作为一个列表:

dat %>%
 mutate(fav_foods = pmap(across(where(is.logical)), ~ names(c(...))[which(c(...))]))

  name  state onions `sweet potatoes` garlic fav_foods
  <chr> <chr> <lgl>  <lgl>            <lgl>  <list>   
1 Tom   WV    TRUE   FALSE            TRUE   <chr [2]>
2 Larry NC    FALSE  TRUE             FALSE  <chr [1]>
3 Beth  NY    TRUE   TRUE             TRUE   <chr [3]>

【讨论】:

    【解决方案2】:

    可以使用c_across 更正OP 的代码,而无需使用dplyr 以外的任何其他外部包

    library(dplyr)
    out <- dat %>% 
           rowwise %>% 
           mutate(fav_foods = list(names(select(.,
                where(is.logical)))[c_across(where(is.logical))])) %>%
           ungroup 
     out
    # A tibble: 3 x 6
      name  state onions `sweet potatoes` garlic fav_foods
      <chr> <chr> <lgl>  <lgl>            <lgl>  <list>   
    1 Tom   WV    TRUE   FALSE            TRUE   <chr [2]>
    2 Larry NC    FALSE  TRUE             FALSE  <chr [1]>
    3 Beth  NY    TRUE   TRUE             TRUE   <chr [3]>
    > out$fav_foods
    [[1]]
    [1] "onions" "garlic"
    
    [[2]]
    [1] "sweet potatoes"
    
    [[3]]
    [1] "onions"         "sweet potatoes" "garlic"        
    

    或者我们可以转为“长”格式,filtername 列并将其绑定到原始格式

    library(dplyr)
    library(tidyr)
    dat %>%
      select(where(is.logical)) %>% 
      mutate(rn = row_number()) %>% 
      pivot_longer(cols = -rn) %>%        
      filter(value) %>% group_by(rn) %>%
      summarise(name1 = list(name), .groups = 'drop') %>% 
      select(name1) %>% 
      bind_cols(dat, .)
    

    -输出

    # A tibble: 3 x 6
    #  name  state onions `sweet potatoes` garlic name1    
    #  <chr> <chr> <lgl>  <lgl>            <lgl>  <list>   
    #1 Tom   WV    TRUE   FALSE            TRUE   <chr [2]>
    #2 Larry NC    FALSE  TRUE             FALSE  <chr [1]>
    #3 Beth  NY    TRUE   TRUE             TRUE   <chr [3]>
    

    【讨论】:

      【解决方案3】:

      使用pivot_long 然后summarize

      output <- dat %>%
        # get all the columns not name/state into variable & TRUE/FALSE values into values
        pivot_longer(cols = !one_of("name", "state"),
          names_to = "variable", values_to = "value") %>%
        # combined all variables that have values TRUE into variable_true
        # variables that have values FALSE into variable_false
        group_by(name, state) %>%
        arrange(variable) %>%
        summarize(variable_true = paste0(variable[value], collapse = ","),
          variable_false = paste0(variable[!value],collapse = ","),
          .groups = "drop")
      

      这是输出

      # A tibble: 3 x 4
        name  state variable_true                variable_false  
        <chr> <chr> <chr>                        <chr>           
      1 Beth  NY    garlic,onions,sweet potatoes ""              
      2 Larry NC    sweet potatoes               "garlic,onions" 
      3 Tom   WV    garlic,onions                "sweet potatoes"
      

      如果您还想拥有以前的列,请添加原始数据

      dat %>% left_join(output, by = c("name", "state"))  
      

      你有这个

      # A tibble: 3 x 7
        name  state onions `sweet potatoes` garlic variable_true                variable_false  
        <chr> <chr> <lgl>  <lgl>            <lgl>  <chr>                        <chr>           
      1 Tom   WV    TRUE   FALSE            TRUE   garlic,onions                "sweet potatoes"
      2 Larry NC    FALSE  TRUE             FALSE  sweet potatoes               "garlic,onions" 
      3 Beth  NY    TRUE   TRUE             TRUE   garlic,onions,sweet potatoes ""   
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-11
        • 2022-12-12
        • 1970-01-01
        • 2017-10-11
        • 2023-02-14
        • 2013-05-11
        • 1970-01-01
        • 2019-09-29
        相关资源
        最近更新 更多