首页 > 解决方案 > 使用 expand.grid 但保留命名字符值

问题描述

我有一个带有命名字符向量的嵌套列表,我expand.grid()用来生成每个可能的值。这进展顺利,但我也想保留命名值。

我的结构如下:

a <- list("id1" = c(setNames(1,"Apple"), setNames(2,"Banana")), "id2" = c(setNames(3,"Jam"), setNames(4,"Peanut butter")))

> a
$id1
 Apple Banana 
     1      2 

$id2
          Jam Peanut butter 
            3             4 

使用expand.grid()给出以下内容:

> expand.grid(a)
  id1 id2
1   1   3
2   2   3
3   1   4
4   2   4

但是,我希望它是:

> a
  id1 id2 id1.name id2.name
1   1   3  Apple    Jam
2   2   3  Banana   Peanut butter
3   1   4  Apple    Jam
4   2   4  Banana   Peanut butter

有没有办法做到这一点?我目前正在尝试创建一个查找表,然后匹配所有值,但这也被证明是困难的。

标签: r

解决方案


我们可以使用crossing.

  1. 循环list命名的vector-map
  2. 使用stackfrombase R转换命名向量 -> 两列ind/valuesdata.frame
  3. 适用crossinginvoke- 类似于do.callfrombase R
  4. 通过调用` data.framelist来展平列以创建普通列
  5. 重命名列(如果需要)
library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
map(a, stack) %>% 
   invoke(crossing, .)%>% 
   invoke(data.frame, .) %>% 
   rename_with(~ str_replace_all(., setNames(c("", ".name"), 
         c("\\.values", "\\.ind"))), everything())
   id1 id1.name id2      id2.name
1   1    Apple   3           Jam
2   1    Apple   4 Peanut butter
3   2   Banana   3           Jam
4   2   Banana   4 Peanut butter

或者另一个选项是expand_grid通过循环使用listwith ,并使用by 赋值 ( )imap创建列名,最后重新排序nameslist:=select

library(stringr)
library(purrr)
library(tidyr)
library(dplyr)
imap_dfc(a, ~ expand_grid(!! .y := .x, 
      !! str_c(.y, ".name") := names(.x))) %>%
     select(matches("^id\\d+$"), everything())

-输出

# A tibble: 4 x 4
    id1   id2 id1.name id2.name     
  <dbl> <dbl> <chr>    <chr>        
1     1     3 Apple    Jam          
2     1     3 Banana   Peanut butter
3     2     4 Apple    Jam          
4     2     4 Banana   Peanut butter

推荐阅读