【问题标题】:R:purrr Finding the list elements that contain named variablesR:purrr 查找包含命名变量的列表元素
【发布时间】:2019-11-06 17:57:51
【问题描述】:

我有一个字符向量 nms 的变量名,这些变量名至少出现在多个文件之一中。如果一个变量存在于多个文件中,则值将相同。

我有一个命名列表test_lst,其中顶级名称是文件的名称。列表的子列表包括文件中变量名称的向量。

我想使用 purrr 遍历 test_lst 并找到包含每个变量的第一个文件,并返回一个命名列表,其中名称是文件名,每个元素是 nms 中变量的向量存在于该文件中。我想按名称索引子列表,而不是按位置。

看起来这应该很容易,我不知道为什么我不能让它工作。

数据:

test_lst <- list(ob1 = list(v1 = list(s1 = "X", s2 = paste0("A", 1:3)), v2 =  paste0("A", 4:8)), 
                 ob2 = list(v1 = list(s1 = "X", s2 = paste0("A", 9:11)), v2 =  paste0("A", 12:16)))

nms <- c (paste0("A", 1:2), paste0("A", 9:10))

非工作代码:

find_vars <- function(var_names, meta){
map_chr(meta, c("v1", "s2")) -> var_vecs
names(var_vecs)<- names(meta)   
map_chr(var_vecs, var_names %in% .) -> out
names(out) <- names(var_vecs)
out
}

find_vars(var_names = nms, meta = test_lst)

想要的输出,一个列表:

$ob1
[1] "A1" "A2"
$ob2
[1] "A9"  "A10"

【问题讨论】:

    标签: r list reference iteration purrr


    【解决方案1】:

    我们可以使用modify_depth

    library(tidyverse)
    modify_depth(test_lst, 2, ~ enframe(.x) %>%
              select(value) %>%
              unnest %>%
              filter(value %in% nms)) %>%
       flatten %>%
       keep(~ nrow(.x) > 0) %>% 
       map(~ .x %>%
              pull(value)) %>% 
       set_names(names(test_lst))
    #$ob1
    #[1] "A1" "A2"
    
    #$ob2
    #[1] "A9"  "A10"
    

    或者我们可以先enframe,然后循环遍历'value'列来对元素进行子集化

    enframe(test_lst) %>% 
         unnest %>% 
         mutate(value = map(value, ~ intersect(nms, unlist(.x))))  %>% 
         unnest %>%
         deframe %>%
         split(names(.))
    

    或者使用我们之前在intersect 中使用的相同符号

    map(test_lst, ~ intersect(nms, unlist(.x)))
    

    或者另一个选项是melt

    library(reshape2)
    melt(test_lst) %>%
         select(L1, value) %>%
         group_by(L1) %>% 
         filter(value %in% nms) %>% 
         {split(as.character(.$value), .$L1)}
    

    【讨论】:

    • 谢谢阿克伦!优秀的答案。我要求一个使用 purrr 提取函数的答案,因为这个问题是我努力理解 purrr 的一部分。但无论如何我都会接受这个答案,既是因为看到三种不同的方法来做到这一点的价值,也因为我从未使用过 enframe 或 deframe ,这似乎是一个具有可比价值的教训。我还发布了另一个更直接地解决 purrr 提取问题的问题。
    【解决方案2】:

    我们可以unlisttest_lst的所有值,并使用intersect找出共同值

    lapply(test_lst, function(x) intersect(unlist(x), nms))
    
    #$ob1
    #[1] "A1" "A2"
    
    #$ob2
    #[1] "A9"  "A10"
    

    如果你想使用purrr,我们可以将lapply改为map

    purrr::map(test_lst, ~intersect(unlist(.), nms))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 2021-07-16
      • 1970-01-01
      • 2021-08-01
      • 2013-02-02
      • 2013-05-30
      相关资源
      最近更新 更多