Zpět na přehled cvičení

Rkový skript ke stažení: R

Co si zde představíme?

Co je to list

Někdy jedna hodnota, vektor či matice plně nepostačují jako výstup funkce. Řada funkcí vrací seznam několika různorodých výstupů, např. rozklady qr či svd z minulého cvičení.

Z <- matrix(1:4, nrow = 2, ncol = 2)
svdZ <- svd(Z)
class(svdZ)
## [1] "list"

K uskupení spolu souvisejících objektů se používá právě list.

Každý prvek listu má své jméno, pod kterým jej lze získat operátorem $:

names(svdZ)
## [1] "d" "u" "v"

V help(svd) se dočteme, že

Každý prvek listu lze získat operátorem $ či [[]]:

svdZ$d           # kratší zápis
## [1] 5.4649857 0.3659662
svdZ[["u"]]      # delší zápis, ale hodí se, když chceme procházet vícero prvků naráz
##            [,1]       [,2]
## [1,] -0.5760484 -0.8174156
## [2,] -0.8174156  0.5760484
svdZ[[3]]        # lze i pomocí čísla, ale musíme znát pořadí, v jakém v listu vystupují
##            [,1]       [,2]
## [1,] -0.4045536  0.9145143
## [2,] -0.9145143 -0.4045536

Jak vytvářet a pracovat se seznamy?

Seznam založíme pomocí příkazu list(), který vytvoří úplně prázdný seznam:

seznam <- list()

Prvky do seznamu přidáváme jednoduše přižazením:

seznam$jmeno <- c("Aneta", "Bohouš", "Ctirad")
seznam$vek <- c(21, 22, 21)
seznam$vyska <- c(173, 182, 175)
seznam$vaha <- c(70, 83, 78)
seznam                                         # defaultní print vytiskne všechny prvky (někdy až moc)
## $jmeno
## [1] "Aneta"  "Bohouš" "Ctirad"
## 
## $vek
## [1] 21 22 21
## 
## $vyska
## [1] 173 182 175
## 
## $vaha
## [1] 70 83 78
seznam$jmeno                                   # vytiskne jen určený prvek
## [1] "Aneta"  "Bohouš" "Ctirad"
seznam$vyska[2]                                # vytiskne druhou položku z udaného prvku
## [1] 182

Zatím je seznam hezky uspořádaný - prvek je vždy vektor o stejné délce. Lze jej pak jednoduše transformovat na matrix či data.frame (o tom si povíme později):

as.data.frame(seznam)
##    jmeno vek vyska vaha
## 1  Aneta  21   173   70
## 2 Bohouš  22   182   83
## 3 Ctirad  21   175   78
as.matrix(as.data.frame(seznam))
##      jmeno    vek  vyska vaha
## [1,] "Aneta"  "21" "173" "70"
## [2,] "Bohouš" "22" "182" "83"
## [3,] "Ctirad" "21" "175" "78"

Při porušení struktury by nám vznikl nepřehledný nesmysl:

seznam$misto_narozeni <- c("Praha", "Brno", "Ostrava", "Klokočí")
# as.data.frame(seznam) # vrací error
seznam$misto_narozeni <- c("Praha", "Brno", "Ostrava", "Klokočí", "Křečkov", "Křenovy")
as.data.frame(seznam) # zde to sice něco vrátí, ale zdvojí se řádky, takže opatrně
##    jmeno vek vyska vaha misto_narozeni
## 1  Aneta  21   173   70          Praha
## 2 Bohouš  22   182   83           Brno
## 3 Ctirad  21   175   78        Ostrava
## 4  Aneta  21   173   70        Klokočí
## 5 Bohouš  22   182   83        Křečkov
## 6 Ctirad  21   175   78        Křenovy

Neužitečného prvku seznamu se zbavíme následovně:

seznam <- within(seznam, rm("vaha"))  # odstraň (rm) objekt "misto_narozeni" uvnitř seznamu, nezapomeň přeuložit
seznam$misto_narozeni <- NULL         # nastav pointer na NULL - nulový objekt
seznam
## $jmeno
## [1] "Aneta"  "Bohouš" "Ctirad"
## 
## $vek
## [1] 21 22 21
## 
## $vyska
## [1] 173 182 175
names(seznam)                         # v obou případech zmizí název proměnné i ze seznamu objektů
## [1] "jmeno" "vek"   "vyska"

Prvkem listu může být další list:

seznam$info <- list()
seznam$info$text <- "Data byla uměle vytvořena pro výukové účely."
seznam$info$rok <- 2025
seznam$info$autor <- list()
seznam$info$autor$jmeno <- "Jan"
seznam$info$autor$prijmeni <- "Vávra"
seznam
## $jmeno
## [1] "Aneta"  "Bohouš" "Ctirad"
## 
## $vek
## [1] 21 22 21
## 
## $vyska
## [1] 173 182 175
## 
## $info
## $info$text
## [1] "Data byla uměle vytvořena pro výukové účely."
## 
## $info$rok
## [1] 2025
## 
## $info$autor
## $info$autor$jmeno
## [1] "Jan"
## 
## $info$autor$prijmeni
## [1] "Vávra"
seznam[["info"]][["autor"]][["prijmeni"]][1] # ke konkrétnímu prvku se dá pomocí [[]] dostat skládáním za sebe
## [1] "Vávra"

List zrušíme pomocí funkce unlist, která pak všechen obsah vypíše do vektoru o stejném typu:

unlist(seznam)
##                                         jmeno1                                         jmeno2 
##                                        "Aneta"                                       "Bohouš" 
##                                         jmeno3                                           vek1 
##                                       "Ctirad"                                           "21" 
##                                           vek2                                           vek3 
##                                           "22"                                           "21" 
##                                         vyska1                                         vyska2 
##                                          "173"                                          "182" 
##                                         vyska3                                      info.text 
##                                          "175" "Data byla uměle vytvořena pro výukové účely." 
##                                       info.rok                               info.autor.jmeno 
##                                         "2025"                                          "Jan" 
##                            info.autor.prijmeni 
##                                        "Vávra"

Úložky na procvičení

Vyřešte si to sami, aniž byste se dívali do řešení (úplně dole vespod skriptu).

  1. Stáhněte si následující Excelovou tabulku s ukázkovými daty o lidech. Utvořte si hezky strukturovaný seznam (dle Vašeho uvážení, jak si myslíte, že to bude užitečné) s informacemi o každém sloupci