Как сделать цикл в списке и получить доступ к именам и атрибутам? - PullRequest
8 голосов
/ 20 сентября 2011

Я применяю функцию к элементам списка.

список имеет names, так что в некотором смысле у каждого элемента есть собственное имя, но как мне получить к нему доступ, когда функция lapply уже извлекла / отделила элемент от списка?

Некоторые фиктивные данные (в качестве внутренней функции я здесь неправильно использую dput):

r <- list(a=structure(1:4, unit="test"), b='abc')
lapply(r, dput)

Здесь я наблюдаю, что dput получает объекты в списке, как если бы к ним обращались с помощью [[, лишенные имени, которое они имеют в содержащем списке.

Поэтому я решил отказаться от идеи использования функций из семейства apply и написать цикл, но мне эта идея не особо нравится, и она обязывает меня построить результат полной функции.

result <- list()
for (name in names(r)) {
  print(name)
  result[[name]] <- dput(r[[name]])
}
result

Какие-нибудь проницательные мысли?

Ответы [ 2 ]

5 голосов
/ 20 сентября 2011

Вы можете смоделировать идею за циклами, все еще используя lapply, передав числовой вектор в lapply и затем используя его в качестве индекса для извлечения элементов из списка, который вы хотите. Это, вероятно, не имеет смысла, но, надеюсь, пример иллюстрирует, что я имею в виду:

lapply(seq_along(r), function(i)dput(r[i]))

structure(list(a = structure(1:4, unit = "test")), .Names = "a")
structure(list(b = "abc"), .Names = "b")
[[1]]
[[1]]$a
[1] 1 2 3 4
attr(,"unit")
[1] "test"



[[2]]
[[2]]$b
[1] "abc"

Основная идея заключается в том, что seq_along(x) возвращает последовательность той же длины, что и x. Например:

> seq_along(r)
[1] 1 2

Подробнее см. ?seq_along.


EDIT

Кажется, это немного быстрее, чем индексирование по имени:

library(rbenchmark)
benchmark(
  xx <- lapply(names(r), function(i)dput(r[i])),
  yy <- lapply(seq_along(r), function(i)dput(r[i])),
  replications=10000)

                                                test replications elapsed relative user.self
1     xx <- lapply(names(r), function(i) dput(r[i]))        10000    1.95 1.026316      1.70
2 yy <- lapply(seq_along(r), function(i) dput(r[i]))        10000    1.90 1.000000      1.66
  sys.self user.child sys.child
1     0.00         NA        NA
2     0.01         NA        NA
2 голосов
/ 20 сентября 2011

Вы можете использовать mapply:

dummy <- function(value, name) {
    list(
        name_of_element = name,
        value_of_element = value
    )
}
str(mapply(dummy, r, names(r), SIMPLIFY=FALSE))
# List of 2
 # $ a:List of 2
  # ..$ name_of_element : chr "a"
  # ..$ value_of_element: atomic [1:4] 1 2 3 4
  # .. ..- attr(*, "unit")= chr "test"
 # $ b:List of 2
  # ..$ name_of_element : chr "b"
  # ..$ value_of_element: chr "abc"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...