Списъци в R програмирането: Как да създаваме и избираме елементи

⚡ Умно обобщение

R List е обект, който съхранява вектори, матрици, рамки от данни и дори други списъци в един контейнер. Функцията list() го изгражда, а двойните квадратни скоби издърпват всеки елемент обратно.

  • 🧺 Смесено съхранение: Списъкът съдържа обекти от различни типове и дължини, което един обикновен вектор не може.
  • 🛠️ Етап на изграждане: list(vect, mat, df) пакетира вектор, матрица и кадър от данни в един обект.
  • 🔢 Достъп до позиция: my_list[[2]] връща самия елемент, докато my_list[2] връща списък с един елемент.
  • ???? ️ Именувани елементи: Маркирането на елементи при създаването им позволява достъп чрез оператора $ или [[„име“]].
  • Редактиране на място: Преназначаването актуализира елемент, а присвояването на NULL го премахва от списъка.
  • 🔗 Сплескване: unlist() свива вложен списък в един атомен вектор за последващ анализ.

R List Създаване на списък в R програмиране и избор на елементи

Какво е R списък?

R списък е обект в R програмирането, който включва матрици, вектори, кадри с данни или списъци в него. R List също се използва за съхраняване на колекция от обекти и използването им, когато имаме нужда от тях. Можем да си представим списъка R като чанта, в която да поставим много различни предмети. Когато трябва да използваме предмет, можем да отворим чантата и да го използваме.

Контрастът с вектора е това, което прави чантата полезна. Векторът принуждава всеки елемент да бъде в един тип, така че поставянето на дума до число превръща числото в текст. Списъкът не прилага такова правило, поради което може да съдържа вектор с пет елемента, двуредов матрица и рамка от 714 реда данни една до друга, без да се променя нито една от тях.

Синтаксис на списък в R

Можем да използваме функцията list(), за да създаваме списъци в R програмирането:

list(element_1, ...)
arguments:
-element_1: store any type of R object
-...: pass as many objects as specifying. each object needs to be separated by a comma

Всеки аргумент може да бъде предаден както гол, така и във формата етикет = стойностГолият аргумент става позиционен елемент, достъпен само по номера си, докато маркираният аргумент също получава име. Базовата R препратка за списък () документира както формуляри, така и отбелязва, че unlist() действа като приблизително обратното на as.list().

Как да създадете списък в R

По-долу е даден стъпка по стъпка процес за създаване на списък в R:

В примера по-долу ще създадем три различни обекта, вектор, матрица и a DataFrame използвайки списък функция в R.

Стъпка 1) Създайте вектор

Използвайте кода по-долу, за да създадете вектор в R

# Vector with numeric from 1 up to 5
vect  <- 1:5

Операторът двоеточие изгражда поредицата 1, 2, 3, 4, 5 като целочислен вектор, а стрелката за присвояване го съхранява под името vect.

Стъпка 2) Създайте матрица

Сега създайте матрица, използвайки следния код

# A 2x 5 matrix
mat  <- matrix(1:9, ncol = 5)
dim(mat)

Тук заслужават внимание два детайла. Мрежа от два реда по пет колони се нуждае от десет стойности, но са предоставени само девет, така че R рециклира последователността и отпечатва предупреждение, че дължината на данните не е делимо от броя на редовете. Тази рециклирана стойност е причината вторият ред на отпечатаната матрица да завършва на 1, а не на 10. Извикването на dim() след това докладва формата.

Изход:

## [1] 2 5

Стъпка 3) Създайте рамка с данни

Създайте рамка с данни в R, като използвате кода по-долу

# select the 10th row of the built-in R data set EuStockMarkets
df <- EuStockMarkets[1:10,]

Коментарът споменава десетия ред, но изразът запазва редове от 1 до 10 от вградената серия EuStockMarkets. Подмножаването също така премахва класа времеви серии, така че това, което се връща, е числова матрица, а не истински кадър от данни, което е точно причината, поради която отпечатаният резултат по-долу съдържа етикети на редове в стил [1,] вместо имена на редове. Обвивайте извикването в as.data.frame() винаги, когато е необходим истински кадър от данни.

Стъпка 4) Създайте списък в R

Сега можем да поставим трите обекта в R списък, като използваме кода по-долу

# Construct list with these vec, mat, and df:
my_list <- list(vect, mat, df)
my_list

Изход:

## [[1]]
## [1] 1 2 3 4 5

## [[2]]
##       [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8    1

## [[3]]
##          DAX    SMI    CAC   FTSE
##  [1,] 1628.75 1678.1 1772.8 2443.6
##  [2,] 1613.63 1688.5 1750.5 2460.2
##  [3,] 1606.51 1678.6 1718.0 2448.2
##  [4,] 1621.04 1684.1 1708.1 2470.4
##  [5,] 1618.16 1686.6 1723.1 2484.7
##  [6,] 1610.61 1671.6 1714.3 2466.8
##  [7,] 1630.75 1682.9 1734.5 2487.9
##  [8,] 1640.17 1703.6 1757.4 2508.4
##  [9,] 1635.47 1697.5 1754.0 2510.5
##  [10,] 1645.89 1716.3 1754.3 2497.4

Трите заглавки с двойни скоби в този изход са позициите в списъка. Нищо не е било изравнено или принудително: елемент едно все още е целочислен вектор, елемент две все още е матрица, а елемент три все още съдържа всичките десет реда с цените на акциите.

Изберете елементи от R списък

След като сме изградили нашия списък, можем да го достъпим доста лесно. Трябва да използваме [[index]], за да изберем елемент от списък. Стойността в двойната квадратна скоба представлява позицията на елемента в списъка, който искаме да изведем.tracт. Например, ако подадем 2 в скобите, R връща втория елемент от списъка.

Сега в това R урок, нека се опитаме да изберем вторите елементи от списъци в R с име my_list, използваме my_list[[2]]

# Print second element of the list
my_list[[2]]

Изход:

##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8    1

Единичните и двойните скоби не са взаимозаменяеми и объркването им е най-честият източник на грешки в списъците. Една скоба запазва обвивката, две я премахват.

Изразяване Какво се връща Клас на резултата Използвайте го, когато
моят_списък[[2]] Самият съхранен елемент Каквото и да е било съхранено, ето матрица Трябва да изчислите върху един елемент
моят_списък[2] Подсписък, съдържащ този един елемент списък Трябва да запазите обвивката на списъка
моят_списък[c(1, 3)] Подсписък на избраните елементи списък Нуждаете се от няколко елемента едновременно
моят_списък[-2] Всеки елемент с изключение на втория списък Трябва да премахнете елемент
# Compare the two bracket styles
class(my_list[[2]])   # the matrix itself
class(my_list[2])     # a list of length one

# Several elements, and everything but one element
my_list[c(1, 3)]
my_list[-2]

Именувани списъци в R

Позиционните индекси са крехки: вмъквайте един елемент и всяко число след него се измества. Именуването на елементите премахва този риск и прави кода да се чете като данните, които описва. Имената могат да бъдат предоставени при изграждането на списъка или добавени впоследствие с names().

# Tag each element at creation time
named_list <- list(numbers = vect, grid = mat, prices = df)

# Three ways to reach the same element
named_list$grid
named_list[["grid"]]
named_list["grid"]      # returns a one-element list

# Read or replace the names later
names(named_list)
names(named_list)[2] <- "grid_2x5"

Операторът $ и двойната скоба се различават по едно отношение, което хваща начинаещите. Операторът $ извършва частично съвпадение, така че named_list$pri все още намира цени, докато named_list[[“pri”]] връща NULL, защото двойните скоби съвпадат точно, освен ако не е подадено exact = FALSE. Частичното съвпадение е удобно в конзолата и опасно в скрипт, така че предпочитайте точната форма в запазения код.

# A compact map of the whole structure
str(named_list)

str() отпечатва по един ред на елемент с неговия тип и размер, което е най-бързият начин да потвърдите, че даден списък съдържа това, което очаквате, преди да го индексирате.

Промяна, добавяне и изтриване на елементи в R списък

След като е създаден, списъкът не е фиксиран. Същите аксесори, които четат елемент, също така пишат в него, така че актуализирането, разширяването и свиването на списък използват обикновено присвояване.

# Replace an element in place
named_list[["numbers"]] <- 1:10

# Add a new element simply by naming it
named_list[["created"]] <- Sys.Date()

# Append without a name: the element lands at the end
named_list <- append(named_list, list(TRUE))

# Delete an element by assigning NULL to it
named_list[["created"]] <- NULL
  • Замяна: Присвояването на съществуващо име презаписва този елемент и оставя позицията му непроменена.
  • Добави: Присвояването на несъществуващо име добавя нов елемент в края на списъка.
  • Добавяне: append() приема списък като втори аргумент, така че обвийте гола стойност в list() преди да я предадете.
  • Изтрий: Присвояването на NULL с двойни скоби премахва елемента и съкращава списъка.

Едно от последствията редовно спъва хората: тъй като NULL означава изтриване, не можете да съхраните действително NULL с двойни скоби. Използвайте присвояване с единични скоби вместо това, както в named_list[“empty”] <- list(NULL), което запазва слота и поставя NULL вътре в него.

Вложени списъци и unlist() в R

Тъй като един списък може да съдържа всеки R обект, той може да съдържа и друг списък. Влагането е начинът, по който конфигурационните обекти, JSON отговорите и резултатите от модела обикновено се представят в R, така че достигането до вложен списък и изравняването му са ежедневни задачи.

# A list whose elements are themselves lists
project <- list(
  meta = list(owner = "analyst", year = 2026),
  data = list(vect, mat)
)

# Chain the accessors to reach an inner value
project$meta$year
project[["data"]][[2]]

# Flatten every level into one atomic vector
flat <- unlist(project)

# Strip a single level and keep the rest as a list
half <- unlist(project, recursive = FALSE)

Сплескването има цена, която си струва да се разбере. unlist() трябва да върне един атомен вектор, така че привежда всяка стойност към най-общия наличен тип, следвайки реда logical, integer, double, character. Вложен списък, който смесва числа с текст, следователно се връща изцяло като текст. Имената на резултата се изграждат чрез съединяване на външния и вътрешния етикет, поради което елементът пристига като meta.owner, а не като owner.

Предайте use.names = FALSE, когато тези съставни имена са нежелани, и задайте recursive = FALSE, когато трябва да се премахне само най-външният слой. Ако стойностите трябва да запазят типовете си, оставете структурата непокътната и работете през списъка, вместо да го изравнявате.

Вградена рамка с данни в R

Списъците често се пълнят с данни, прочетени от диск или от интернет, така че е полезно да видим как един кадър с данни пристига, преди да бъде съхранен в такъв. Преди да създадем наш собствен кадър с данни, можем да разгледаме набора от данни R, достъпен онлайн. Наборът от данни за затвора е с размер 714×5. Можем да разгледаме бързо долната част на кадъра с данни с функцията tail(). По аналогия, head() показва горната част на кадъра с данни. Можете да укажете броя на показаните редове с head(df, 5). Ще научим повече за функцията read.csv() в... импортиране на данни в R настойнически.

PATH <-'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/prison.csv'
df <- read.csv(PATH)[1:5]
head(df, 5)

Изход:

##   X state year govelec black
## 1 1     1   80       0 0.2560
## 2 2     1   81       0 0.2557
## 3 3     1   82       1 0.2554
## 4 4     1   83       0 0.2551
## 5 5     1   84       0 0.2548

[1:5], който следва read.csv(), избира първите пет колони, а не първите пет реда, защото самият кадър от данни е списък от колони. Индексирането с единични скоби в списък връща по-малък списък и тук този по-малък списък все още е кадър от данни.

Можем да проверим структурата на рамката с данни с str:

# Structure of the data
str(df)

Изход:

## 'data.frame':    714 obs. of  5 variables:
##  $ X      : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ state  : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ year   : int  80 81 82 83 84 85 86 87 88 89 ...
##  $ govelec: int  0 0 1 0 0 0 1 0 0 0 ...
##  $ black  : num  0.256 0.256 0.255 0.255 0.255 ...

Всички променливи се съхраняват в числен формат. Префиксът $ на всеки ред е същият оператор, използван по-рано в именувани списъци, което потвърждава, че рамката от данни е списък от колони с еднаква дължина, носещи правоъгълен етикет. Всичко научено за именуването, избирането и изтриването на елементи от списъка следователно се пренася директно в R типове данни и към колоните на рамката с данни.

Въпроси и Отговори

Векторът принуждава всеки елемент да споделя един тип, така че смесването на текст и числа привежда всичко към символ. Списъкът запазва всеки елемент точно както е предоставен, включително вектори, матрици и функции с различна дължина. Използвайте typeof(), за да различите двата типа.

Извикайте is.list(x), която връща TRUE за списъци и списъци с двойки. class(x) съобщава класа на обекта, докато typeof(x) връща „list“ дори за рамки с данни, защото рамката с данни е списък от колони с еднаква дължина отдолу.

length(my_list) брои само елементите от най-високо ниво, така че вложените списъци все още се броят за един. lengths(my_list) отчита размера на всеки елемент в едно извикване, което е по-бързо и по-ясно от loo.ping когато елементите се различават.

lapply(my_list, FUN) прилага a функция към всеки елемент и връща списък. sapply() опростява резултата до вектор или матрица, където е възможно. Обикновен for цикъл върху seq_along(my_list) също работи и се чете ясно.

Когато всеки елемент е с еднаква дължина, as.data.frame(my_list) работи директно. За списък с редове с еднаква ширина, do.call(rbind, my_list) ги подрежда първо. dplyr екосистемата предлага as_tibble(), когато типовете колони трябва да останат недокоснати.

Списъците нямат вградено сортиране, така че напр.tracПърво използваме сравним ключ: my_list[order(sapply(my_list, length))] пренарежда по размер на елемента. За правоъгълни данни, конвертираме в рамка и сортиране на рамката от данни с order() вместо това.

Асистентите с изкуствен интелект четат изхода на str() и обясняват защо даден индекс е върнал NULL или подсписък вместо стойност. Те също така предлагат правилната форма на скобите, проектират lapply() конвейери и маркират безшумно преобразуване на тип, преди то да повреди резултата.

Да. Копилот на GitHub работи в RStudio 2023.09.0 и по-нови версии чрез Инструменти, Глобални опции, след това настройката на асистента за код. Той завършва извикванията на list(), names() и unlist() от коментар, въпреки че всяко предложение все още се нуждае от преглед.

Обобщете тази публикация с: