Основы программирования: списки
29/12/13 20:54 Относится к категории: Анализ данных | R
"Список - это упорядоченный набор объектов (компонентов). Список может объединять разные (возможно, не связанные между собой) объекты под одним именем. К примеру, список может представлять собой сочетание векторов, матриц, таблиц данных и даже других списков" (Роберт Кабаков. Анализ и визуализация данных на языке R). Главное преимущество списков связано с их гибкостью. Во-первых, как уже упомянуто, они могут включать данные и объекты разных типов. Во-вторых, размер списков не задается при их создании и может меняться в соответствии с интересами исследователя. Эти две особенности отличают списки от векторов. Третьим, но менее важным отличием является то, что доступ к элементам списков возможно как по индексам, так и по ключевым словам. В этом смысле списки в R объединяют свойства как списков, так и словарей (если использовать Python-овскую терминологию).
Именно списки очень удобно использовать в работе циклов - добавление новых элементов будет идти не по пути перезаписи списка, а по пути его расширения. Благодаря использованию циклов, условных операторов и списков открываются широкие возможности решения творческих задач как в рамках программирования в целом, так и в рамках анализа данных в частности.
Именно списки очень удобно использовать в работе циклов - добавление новых элементов будет идти не по пути перезаписи списка, а по пути его расширения. Благодаря использованию циклов, условных операторов и списков открываются широкие возможности решения творческих задач как в рамках программирования в целом, так и в рамках анализа данных в частности.
Создание списков
Список создается с помощью функции list(). При этом есть два варианта - с указанием имен и без него. Если при создании имена указываются (см. 1 строку синтаксиса), то доступ к соответствующему элементу может осуществляться как с помощью индексирования, так и с помощью самих имен. Если же имена не указываются (см. 6 строку синтаксиса), то остается только доступ с помощью индексирования.
Список создается с помощью функции list(). При этом есть два варианта - с указанием имен и без него. Если при создании имена указываются (см. 1 строку синтаксиса), то доступ к соответствующему элементу может осуществляться как с помощью индексирования, так и с помощью самих имен. Если же имена не указываются (см. 6 строку синтаксиса), то остается только доступ с помощью индексирования.
1 2 3 4 5 6 7 8 | > test <- list(money=c(300,400,500),name=c("Аня","Люда","Таня")) > test$money [1] 300 400 500 > test[[2]] [1] "Аня" "Люда" "Таня" > testNew <- list(c(200,300,400),c("Коля","Паша","Вася")) > testNew[[2]] [1] "Коля" "Паша" "Вася" |
Как видно, первый список (test), включает два элемента: числовой вектор с именем "money" и текстовый с именем "name". Далее продемонстрированы способы доступа к его элементам с помощью имени и с помощью индекса. Следующий список (testNew) идентичен первому с тем отличием, что его элементы не содержат имен.
Рассмотрим еще один пример, в котором список еще более похож на склад различных элементов:
Рассмотрим еще один пример, в котором список еще более похож на склад различных элементов:
9 10 11 12 13 14 15 16 17 18 19 20 21 | > dolla <- c(300,400,500) > ppl <- c("Аня","Люда","Таня") > someData <- data.frame(dolla,ppl) > testNew <- list(df=someData,c(T,T,F),end=88) > testNew[[2]][3] [1] FALSE > testNew$df dolla ppl 1 300 Аня 2 400 Люда 3 500 Таня > testNew[[3]] [1] 88 |
В данном случае сначала создается фрейм данных someData, после чего он и другие данные записываются в список. При этом два элемента списка имеют имена, один - нет.
Доступ к элементам списка
Как уже было показано, доступ к элементам списка осуществляется с помощью указания индекса в квадратных скобках, а также с помощью указания имени элемента после знака "$" (конечно если элемент имеет имя).
При использовании индекса можно использовать как одинарные квадратные скобки, так и двойные. Различие в том, что в первом случае возвращаемый объект будет новым списком с одним элементом, во втором - будет возвращен тот тип объекта, к которому мы возвращаемся.
Чтобы понять о чем идет речь рассмотрим пример:
Как уже было показано, доступ к элементам списка осуществляется с помощью указания индекса в квадратных скобках, а также с помощью указания имени элемента после знака "$" (конечно если элемент имеет имя).
При использовании индекса можно использовать как одинарные квадратные скобки, так и двойные. Различие в том, что в первом случае возвращаемый объект будет новым списком с одним элементом, во втором - будет возвращен тот тип объекта, к которому мы возвращаемся.
Чтобы понять о чем идет речь рассмотрим пример:
22 23 | > itIsNewList <- testNew[1] > itIsNewDataFrame <- testNew[[1]] |
В первой строке предыдущего синтаксиса создается новый список с одним элементом - фреймом данных. Во второй строке будет получен сам фрейм данных, а не список.
При использовании ключевых слов для доступа к элементам списка, они указываются либо после знака "$", либо в квадратных скобках (само слово при этом указывается в кавычках):
При использовании ключевых слов для доступа к элементам списка, они указываются либо после знака "$", либо в квадратных скобках (само слово при этом указывается в кавычках):
24 25 26 | > oneNumber <- testNew$end > oneNumber <- testNew["end"] > oneNumber <- testNew[["end"]] |
Первый способ ведет к созданию скаляра, второй - к созданию нового списка с одним элементом-скаляром, третий - к созданию скаляра.
Добавление и удаление элементов списка
Новые элементы списка добавляются с помощью присваивания. При этом указывается индекс или имя элемента, определяющие куда будет записана информация. Здесь возможны следующие варианты: а) если указывается индекс уже имеющегося элемента списка (например, индекс 3 для списка с тремя элементами), то новая инфомация записывается вместо старой; б) то же самое справедливо, когда используется имя уже имеющегося элемента; в) если указывается индекс, элемента которого еще нет (например, индекс 5 для списка с тремя элементами), то будет соответствующая информация появится на указанной позиции, а все предыдущие элементы (в нашем случае 4 элемент) будут обозначены как не имеющие данных (NULL); г) если при создании используется еще не существующее имя, то соответствующий элемент с этим именем будет записан на новую свободную позицию, созданную в конце списка (в нашем случае это будет позиция с индексом 6).
Рассмотрим синтаксис для каждого из вариантов:
Новые элементы списка добавляются с помощью присваивания. При этом указывается индекс или имя элемента, определяющие куда будет записана информация. Здесь возможны следующие варианты: а) если указывается индекс уже имеющегося элемента списка (например, индекс 3 для списка с тремя элементами), то новая инфомация записывается вместо старой; б) то же самое справедливо, когда используется имя уже имеющегося элемента; в) если указывается индекс, элемента которого еще нет (например, индекс 5 для списка с тремя элементами), то будет соответствующая информация появится на указанной позиции, а все предыдущие элементы (в нашем случае 4 элемент) будут обозначены как не имеющие данных (NULL); г) если при создании используется еще не существующее имя, то соответствующий элемент с этим именем будет записан на новую свободную позицию, созданную в конце списка (в нашем случае это будет позиция с индексом 6).
Рассмотрим синтаксис для каждого из вариантов:
27 28 29 30 31 32 33 34 35 36 37 38 | > testNew[[3]] <- 99 # вариант а > testNew[[3]] [1] 99 > testNew$end <- 111 # вариант б > testNew[[3]] [1] 111 > testNew[[5]] <- c(88,99) # вариант в > testNew[[4]] NULL > testNew$last <- FALSE # вариант г > testNew[[6]] [1] FALSE |
Удаляются элементы с помощью присваивания им значения NULL (можно прописать как с помощью индекса, так и с помощью имени). При этом если удаляется любой элемент кроме последнего, то все остальные сдвигаются влево. Например, если в списке из пяти элементов удалить третий, то первый и второй останутся на своих местах, четвертый станет третим (займет место удаленного элемента), а пятый - четвертым.
В предыдущем примере удалим четвертый пустой элемент:
В предыдущем примере удалим четвертый пустой элемент:
39 40 41 42 43 | > length(testNew) # проверяем длину объекта (количество элементов) [1] 6 > testNew[[4]] <- NULL # удаляем пустой элемент > length(testNew) # опять проверяем длину объекта [1] 5 |
В завершение рассмотрим синтаксис c использованием списков из реальной практики:
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | > for (i in 1:17) { test <- allDatatest[which(allDatatest$godNew == filt[i]) , ] testNew <- data.frame(c(1:length(test$godNew))) for (j in (1:31)) { if (mean(test[,j])!=-999 & sd(test[,j], na.rm=T)!= 0) { testNew <- cbind(testNew,test[,j]) names(testNew)[length(testNew)] <- nameS[j] } } testNew$godNew <- NULL testNew$c.1.length.test.godNew.. <- NULL matr <- as.matrix(testNew) matr[matr==-999]<-NA testNew <- as.data.frame(matr) listForPrestVar[[i]] <- testNew } |
Задача этого синтаксиса подготовка фреймов данных для каждого года (testNew) исследования и их запись в список listForPrestVar (строка синтаксиса 58). После завершения цикла список будет состоять из 17 элементов. В дальнейшем он используется для обработки каждого фрейма данных по отдельности.
статью подготовил кандидат социологических наук Сергей Дембицкий
Вверх
blog comments powered by Disqus