Szukaj…


Szybkie wprowadzenie do list

Ogólnie rzecz biorąc, większość obiektów, z którymi użytkownik wchodziłby w interakcje, byłby wektorem; np. wektor numeryczny, wektor logiczny. Obiekty te mogą przyjmować tylko jeden typ zmiennej (wektor numeryczny może zawierać tylko liczby).

Lista byłaby w stanie przechowywać w niej dowolną zmienną typu, dzięki czemu trafiłaby do ogólnego obiektu, który może przechowywać dowolne potrzebne zmienne.

Przykład inicjalizacji listy

exampleList1 <- list('a', 'b')
exampleList2 <- list(1, 2)
exampleList3 <- list('a', 1, 2)

Aby zrozumieć dane zdefiniowane na liście, możemy użyć funkcji str.

str(exampleList1)
str(exampleList2)
str(exampleList3)

Podzbiór list rozróżnia między wypakowaniem wycinka listy, tj. Uzyskaniem listy zawierającej podzbiór elementów z oryginalnej listy, a wypakowaniem pojedynczego elementu. Użycie [ operatora powszechnie używanego dla wektorów tworzy nową listę.

# Returns List
exampleList3[1]
exampleList3[1:2]

Aby uzyskać pojedynczy element, użyj [[ zamiast.

# Returns Character
exampleList3[[1]]

Wpisy na liście mogą mieć nazwy:

exampleList4 <- list(
    num = 1:3,
    numeric = 0.5,
    char = c('a', 'b')
)

Wpisy na nazwanych listach są dostępne według ich nazw zamiast indeksu.

exampleList4[['char']]

Alternatywnie można użyć operatora $ , aby uzyskać dostęp do nazwanych elementów.

exampleList4$num

Ma to tę zaletę, że jest szybsze pisanie i może być łatwiejsze do odczytania, ale ważne jest, aby zdawać sobie sprawę z potencjalnej pułapki. Operator $ używa częściowego dopasowania do identyfikacji pasujących elementów listy i może dawać nieoczekiwane wyniki.

exampleList5 <- exampleList4[2:3]

exampleList4$num
# c(1, 2, 3)

exampleList5$num
# 0.5

exampleList5[['num']]
# NULL

Listy mogą być szczególnie przydatne, ponieważ mogą przechowywać obiekty o różnych długościach i różnych klasach.

## Numeric vector
exampleVector1 <- c(12, 13, 14)
## Character vector
exampleVector2 <- c("a", "b", "c", "d", "e", "f")
## Matrix
exampleMatrix1 <- matrix(rnorm(4), ncol = 2, nrow = 2)
## List
exampleList3 <- list('a', 1, 2)

exampleList6 <- list(
    num = exampleVector1, 
    char = exampleVector2,
    mat = exampleMatrix1, 
    list = exampleList3
)
exampleList6
#$num
#[1] 12 13 14
#
#$char
#[1] "a" "b" "c" "d" "e" "f"
#
#$mat
#          [,1]        [,2]
#[1,] 0.5013050 -1.88801542
#[2,] 0.4295266  0.09751379
#
#$list
#$list[[1]]
#[1] "a"
#
#$list[[2]]
#[1] 1
#
#$list[[3]]
#[1] 2

Wprowadzenie do list

Listy pozwalają użytkownikom przechowywać wiele elementów (takich jak wektory i macierze) w jednym obiekcie. Możesz użyć funkcji list aby utworzyć listę:

l1 <- list(c(1, 2, 3), c("a", "b", "c"))
l1
## [[1]]
## [1] 1 2 3
## 
## [[2]]
## [1] "a" "b" "c"

Zauważ, że wektory, które składają się na powyższą listę, są różnymi klasami. Listy pozwalają użytkownikom grupować elementy różnych klas. Każdy element na liście może mieć również nazwę. Do nazw list można uzyskać dostęp za pomocą funkcji names i są one przypisywane w taki sam sposób, jak nazwy wierszy i kolumn są przypisywane w macierzy.

names(l1)
## NULL
names(l1) <- c("vector1", "vector2")
l1
## $vector1
## [1] 1 2 3
## 
## $vector2
## [1] "a" "b" "c"

Często łatwiej i bezpieczniej jest zadeklarować nazwy list podczas tworzenia obiektu listy.

l2 <- list(vec = c(1, 3, 5, 7, 9),
       mat = matrix(data = c(1, 2, 3), nrow = 3))
l2
## $vec
## [1] 1 3 5 7 9
## 
## $mat
##      [,1]
## [1,]    1
## [2,]    2
## [3,]    3
names(l2)
## [1] "vec" "mat"

Powyżej listy znajdują się dwa elementy, zwane „vec” i „mat”, wektor i macierz, odpowiednio.

Powody korzystania z list

Dla przeciętnego użytkownika R struktura listy może wydawać się jedną z bardziej skomplikowanych struktur danych, którymi można manipulować. Nie ma gwarancji, że wszystkie zawarte w nim elementy są tego samego typu; Nie ma żadnej gwarantowanej struktury tego, jak skomplikowana / nieskomplikowana byłaby lista (elementem na liście może być lista)

Jest to jednak jeden z głównych powodów, dla których należy używać list do przekazywania parametrów między funkcjami.

# Function example which returns a single element numeric vector
exampleFunction1 <- function(num1, num2){
    result <- num1 + num2
    return(result)
}

# Using example function 1
exampleFunction1(1, 2)

# Function example which returns a simple numeric vector
exampleFunction2 <- function(num1, num2, multiplier){
    tempResult1 <- num1 + num2
    tempResult2 <- tempResult1 * multiplier
    result <- c(tempResult1, tempResult2)
    return(result) 
}

# Using example function 2
exampleFunction2(1, 2, 4)

W powyższym przykładzie zwrócone wyniki są po prostu wektorami liczbowymi. Tak prostych wektorów nie można pominąć.

W tym miejscu należy zauważyć, że generalnie funkcje R zwracają tylko 1 wynik na raz (można użyć, jeśli warunki zwracają różne wyniki). Jeśli jednak zamierzasz utworzyć funkcję, która pobiera zestaw parametrów i zwraca kilka typów wyników, takich jak wektor numeryczny (wartość ustawień) i ramka danych (z obliczeń), musisz zrzucić wszystkie te wyniki na listę przed zwrotem.

# We will be using mtcars dataset here
# Function which returns a result that is supposed to contain multiple type of results
# This can be solved by putting the results into a list
exampleFunction3 <- function(dataframe, removeColumn, sumColumn){
    resultDataFrame <- dataframe[, -removeColumn]
    resultSum <- sum(dataframe[, sumColumn])
    resultList <- list(resultDataFrame, resultSum)
    return(resultList)
}

# Using example function 3
exampleResult <- exampleFunction3(mtcars, 2, 4)
exampleResult[[1]]
exampleResult[[2]]

Konwertuj listę na wektor, zachowując puste elementy listy

Gdy chce się przekonwertować listę na obiekt wektorowy lub data.frame, puste elementy są zwykle upuszczane.

Problemem może być to, że tworzona jest lista o pożądanej długości z pewnymi pustymi wartościami (np. Tworzona jest lista zawierająca n elementów, które mają być dodane do macierzy MXN, data.frame lub data.table). Możliwe jest jednak bezstratne przekształcenie listy w wektor, zachowując puste elementy:

res <- list(character(0), c("Luzhuang", "Laisu", "Peihui"), character(0), 
    c("Anjiangping", "Xinzhai", "Yongfeng"), character(0), character(0), 
    c("Puji", "Gaotun", "Banjingcun"), character(0), character(0), 
    character(0))
res
[[1]]
character(0)

[[2]]
[1] "Luzhuang" "Laisu"    "Peihui"  

[[3]]
character(0)

[[4]]
[1] "Anjiangping" "Xinzhai"     "Yongfeng"   

[[5]]
character(0)

[[6]]
character(0)

[[7]]
[1] "Puji"       "Gaotun"     "Banjingcun"

[[8]]
character(0)

[[9]]
character(0)

[[10]]
character(0)
res <- sapply(res, function(s) if (length(s) == 0) NA_character_ else paste(s, collapse = " "))
res
 [1] NA                             "Luzhuang Laisu Peihui"        NA                             "Anjiangping Xinzhai Yongfeng" NA      

 [6] NA                             "Puji Gaotun Banjingcun"       NA                             NA                             NA

Serializacja: używanie list do przekazywania informacji

Istnieją przypadki, w których konieczne jest zestawienie danych różnych typów. Na przykład w Azure ML konieczne jest przekazywanie informacji z modułu skryptu R do innego wyłącznie poprzez ramki danych. Załóżmy, że mamy ramkę danych i liczbę:

> df
       name height        team fun_index title age         desc Y
1    Andrea    195       Lazio        97     6  33   eccellente 1
2      Paja    165  Fiorentina        87     6  31       deciso 1
3      Roro    190       Lazio        65     6  28       strano 0
4    Gioele     70       Lazio       100     0   2    simpatico 1
5     Cacio    170    Juventus        81     3  33         duro 0
6     Edola    171       Lazio        72     5  32     svampito 1
7    Salami    175       Inter        75     3  30  doppiopasso 1
8    Braugo    180       Inter        79     5  32          gjn 0
9     Benna    158    Juventus        80     6  28     esaurito 0
10   Riggio    182       Lazio        92     5  31     certezza 1
11 Giordano    185        Roma        79     5  29        buono 1

> number <- "42"

Możemy uzyskać dostęp do tych informacji:

> paste(df$name[4],"is a",df3$team[4], "supporter." )
[1] "Gioele is a  Lazio supporter."
> paste("The answer to THE question is", number )
[1] "The answer to THE question is 42"

Aby umieścić różne typy danych w ramce danych, musimy użyć obiektu listy i serializacji. W szczególności musimy umieścić dane na ogólnej liście, a następnie umieścić listę w określonej ramce danych:

l <- list(df,number)
dataframe_container <- data.frame(out2 = as.integer(serialize(l, connection=NULL)))

Po zapisaniu informacji w ramce danych musimy dokonać deserializacji w celu ich wykorzystania:

#----- unserialize ----------------------------------------+
unser_obj <- unserialize(as.raw(dataframe_container$out2))
#----- taking back the elements----------------------------+
df_mod        <- unser_obj[1][[1]]  
number_mod    <- unser_obj[2][[1]]

Następnie możemy sprawdzić, czy dane są poprawnie przesyłane:

> paste(df_mod$name[4],"is a",df_mod$team[4], "supporter." )
[1] "Gioele is a  Lazio supporter."
> paste("The answer to THE question is", number_mod )
[1] "The answer to THE question is 42"


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow