R: purrr Поиск элементов списка, которые содержат именованные переменные - PullRequest
1 голос
/ 25 июня 2019

У меня есть символьный вектор 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"

Ответы [ 2 ]

1 голос
/ 25 июня 2019

Мы можем unlist все значения test_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))
1 голос
/ 25 июня 2019

Мы можем использовать 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)}
...