2016-11-08 5 views
1

Я чувствую, что у меня есть хорошее представление о data.frames и о том, как они работают, но некоторые аспекты списков меня путают.Понимание поведения списка

Вот некоторые воспроизводимые данные для запуска:

list_a <- structure(list(`one` = structure(list(
    words = c("a", "b","c", "d", "e", "f")), .Names = "words", class = "data.frame", row.names = c(NA,-6L)), 
    `two` = structure(list(words = c("a","s","t","z")), .Names = "words", class = "data.frame", row.names = c(NA, -4L))), 
    .Names = c("one", "two")) 

Это дает нам:

list_a 
$one 
    words 
1  a 
2  b 
3  c 
4  d 
5  e 
6  f 

$two 
    words 
1  a 
2  s 
3  t 
4  z 

Теперь я хочу, чтобы перебрать список, чтобы вернуть некоторые из результатов в data.frames.

list <- list() 

for(i in list_a){list <- append(list, list_a$i$words)} 

Это результат не дает результатов в списке. ни делает:

for(i in list_a){list <- append(list, list_a[[i]]$words)} 
Error in list_a[[i]] : invalid subscript type 'list' 

Я думал, возможно, причина моя первая петля не работает, что я использовал list_a$i$words без определения я как правильные имена. Так что я пробовал:

for(i in names(list_a)){list <- append(list, list_a$i$words)} 

Это все еще дает мне список длины 0.

Так что я не понимаю, почему попытки я попытался дать техника его подводит результаты я ожидал, я не знаю, почему, используя индексы дал мне ошибку и в конце концов я понял, правильный синтаксис:

for(i in list_a){list2 <- append(list2, i$words)}

Однако я не знаю, почему это работает при использовании метода имен не?

+1

Не добавляйте к объекту в цикле 'for'. Положитесь на предварительное выделение (или используйте функции циклирования, такие как 'lapply', которые делают это для вас). Во всяком случае, используйте 'i $ words' вместо' list_a $ i $ words'. Цикл повторяется над элементами списка, т. Е. 'I' содержит элементы списка, а не их индексы. – Roland

+0

Спасибо, любая проницательность по качеству вопроса, как кто-то запустил его, и я подумал из примера данных, чтобы ясность я пометил все коробки? – Olivia

ответ

0

Аргументы for выражения в R состоит из:

  • LHS, итератор, который будет принимать каждое значение РИТ
  • in, язык ключевое слово
  • РИТ, вектор, длина из которых определяется количество итераций, которые будут происходить.

Когда вы настроили первый цикл, RHS был вектором длины 2 типа «list». На LHS у вас есть i, который представляет собой кадр данных с одним столбцом. Затем вы попросили $ извлечь «i» из списка_a, который был оценен до NULL. В вашей второй петле RHS был вектором длины 2 типа «характер». То же самое произошло.

$ не оценивает его индекс. Вместо этого используйте [[, и вы получите ответ, который вы ожидаете во втором цикле.

# initialize 
list <- list() 
# loop 
for (i in names(list_a)) { 
    list <- append(list, list_a[[i]]$words) 
} 
list 
# [[1]] 
# [1] "a" 
# 
# [[2]] 
# [1] "b" 
# ... 

Как упоминалось Роланд, добавление очень дорого в R, так как каждая итерация создает новую копию объекта. Вот одна альтернатива попробовать:

# create a data frame using all of list_a, 
# coerce to character vector 
# then coerce to list 
as.list(unname(unlist(do.call(what = "rbind", args = list_a)))) 

Обратите внимание, что «data.frame» объекты просто «список» объектов с атрибутом «data.frame» класса применяется. Таким образом, вы увидите такое же поведение при работе с data.frames и $ с неоценимыми именами, как со списками.Попробуйте это:

# print mtcars data.frame 
mtcars 
# set class attribute to NULL 
class(mtcars) <- NULL 
# mtcars is just a list now :-) 
mtcars 

EDIT: $ и [[ операторы, которые просто означает, что они являются функциями, которые могут быть использованы особым образом. Вы можете использовать их как обычные функции, передавая их аргументы в круглых скобках.

# $ is a function 
`$`(list_a, "one") 
# words 
# 1  a 
# 2  b 
# ... 

Поведение этих функций различно. [[ ожидает объект, который он интерпретирует. $ ожидает имя элемента, которое он пытается найти.

i <- "one" 
# $ is a function, but there is no element "i" 
`$`(list_a, i) 
# NULL 
# [[ is a function, and an element "one" is present 
`[[`(list_a, i) 
# words 
# 1  a 
# 2  b 
# ... 
+0

Можете ли вы объяснить '' '' '' '[[]]' немного больше. Почему 'list_a $ i $ words' оценивает значение' NULL', но 'i $ words' корректно, если в обоих случаях мы действительно смотрим на' list_a' ?? – Olivia

+0

@ Оливия, отредактированный ответ с дополнительным объяснением. Значит ли это, что яснее? – CSJCampbell

+0

Отличное спасибо! – Olivia

Смежные вопросы