Список именованных векторов из списка таблиц в R

У меня, казалось бы, очень простая задача, но я не могу понять, что делаю не так. У меня есть список из 3 тибблей Xx2 (в примере 2x2), имеющих вектор символов и целочисленный вектор. Я хочу преобразовать его в список из 3 именованных векторов, где буквы - это векторные элементы, а числа - это имена. Вот мой подход:

tbl <- tibble(numbers=c(1:2), letters=letters[1:2])
vec_names <- c("name1", "name2", "name3")
lst <- list(tbl, tbl, tbl)
names(lst) <- vec_names
lst_n <- lapply(lst, function(x) x[["letters"]]) 
lst_n <- sapply(vec_names, 
    function(x) names(lst_n[[x]]) <- lst[[x]]$numbers)

Я получаю такой результат

lst_n
     name1 name2 name3
[1,]     1     1     1
[2,]     2     2     2

и я не вижу своей ошибки. Делает

names(lst_n[["name1"]]) <- lst[["name1"]]$numbers

дает мне именно то, что я хочу для "name1", но почему он не работает с sapply?

У меня был [] раньше, и я изменил его на [[]], чтобы получить доступ к таблицам внутри списка, а не к элементам списка, но это все еще не работает. Кто-нибудь может помочь? Это кажется очень простой задачей.


person n.o    schedule 02.10.2018    source источник
comment
sapply попытайтесь упростить результат по умолчанию, если вы следуете за списком в качестве вывода, просто используйте lapply. См. этот ответ для получения дополнительных сведений о семействе приложений.   -  person Tensibai    schedule 02.10.2018
comment
comment
Сделайте ваш пример воспроизводимым. Это облегчит другим вам помощь.   -  person Jaap    schedule 02.10.2018
comment
Небольшой совет, вам не нужна анонимная функция для lapply(lst, function(x) x[["letters"]]) , это просто lapply(lst, "[[", "letters")   -  person Gregor Thomas    schedule 02.10.2018
comment
Приносим извинения за сбой кода, остатки моего исходного кода.   -  person n.o    schedule 02.10.2018


Ответы (1)


Вот один из способов сделать это в одной анонимной функции:

z = lapply(lst, function(x) {
  result = x$letters
  names(result) = x$numbers
  return(result)
})

str(z)
# List of 3
#  $ name1: Named chr [1:2] "a" "b"
#   ..- attr(*, "names")= chr [1:2] "1" "2"
#  $ name2: Named chr [1:2] "a" "b"
#   ..- attr(*, "names")= chr [1:2] "1" "2"
#  $ name3: Named chr [1:2] "a" "b"
#   ..- attr(*, "names")= chr [1:2] "1" "2"

Ваш подход застрял, потому что после того, как вы извлекли все letters, вам нужно перебрать оба letters и numbers, чтобы установить имена, но lapply позволяет вам перебирать только один элемент. (И присвоение внутри lapply не работает, единственное, что имеет значение, - это возвращаемый объект.)

Если вы не могли использовать описанный выше подход, выполняя действия за один проход через lst, вы можете вместо этого использовать Map, который выполняет итерацию по нескольким спискам. Мы будем использовать функцию setNames вместо names<-(), которая вызывается, когда вы пытаетесь выполнить names(x) <-.

Map(
  f = setNames,
  object = lapply(lst, "[[", "letters"),
  nm = lapply(lst, "[[", "numbers")
)
# $`name1`
#   1   2 
# "a" "b" 
# 
# $name2
#   1   2 
# "a" "b" 
# 
# $name3
#   1   2 
# "a" "b" 
person Gregor Thomas    schedule 02.10.2018
comment
Отлично, спасибо Грегор! Я думал о вашем первом решении, но не был уверен, сработает ли присвоение значений и чисел в одном из них. Также ваше второе решение кажется очень элегантным, и я попробую использовать больше. Спасибо еще раз! - person n.o; 02.10.2018
comment
Я рад, что вам нравится второе решение, но первое мне нравится больше. Первый способ проходит через lst один раз, собирая все соответствующие части и склеивая их вместе, чтобы получить результат. Второе решение проходит через lst один раз, чтобы получить буквы, снова чтобы получить числа, а затем перебирает их, чтобы склеить их в результате. - person Gregor Thomas; 02.10.2018
comment
Согласовано. В моем случае время выполнения на самом деле не имеет значения, поскольку я только рисую результаты, и мне кажется полезным познакомиться с Map () для других приложений. - person n.o; 04.10.2018