Indexace

Zpracovávání výzkumných dat pomocí jazyka R

Program

  • opakování z minulé hodiny
  • pár organizačních informací
  • kontrola domácího úkolu
  • indexace pomocí [ ]
  • indexace pomocí $
  • indexace pomocí balíčku dplyr

Novinky

  1. U každé hodiny budou nyní cvičení na doma navíc. Bude se jednat o směs již probrané látky a problémů na zapřemýšlení. Jsou nepovinné - budete k nim mít i řešení, ale klidně mi je můžete poslat pro kontrolu / zpětnou vazbu.

  2. V horním menu stránek kurzu nyní naleznete odkaz na rezervační stránku konzultací. Pokud něco budete potřebovat probrat, ať již obsah kurzu či pomoc s R, můžete mi bud´ napsat a nebo si zde přímo rezervovat termín. Součástí jsou i všeobecné R konzultace, pokud víte, že by je vaši kolegové využili, klidně odkaz předejte.

Kontrola domácí práce

Úloha 1

Vytvořte vektor, který v sobě bude mít větu “Tea is better than coffee”. Pokuste se přijít na to, jakým způsobem byste mohli z tohoto vektoru vytvořit druhý vektor, co bude obsahovat hodnoty “Tea” “is” “better” “than” “coffee”.

  1. Vytvoříme vektor o jedné hodnotě "Tea is better than coffee".

    coldHardTruth <- c("Tea is better than coffee"); coldHardTruth
    [1] "Tea is better than coffee"
    length(coldHardTruth) #delka 1
    [1] 1
  2. Rozdělíme ho tak, že každé slovo bude vlastní hodnota.

    rozdeleneHodnoty <- strsplit(coldHardTruth, " "); rozdeleneHodnoty
    [[1]]
    [1] "Tea"    "is"     "better" "than"   "coffee"
  3. Zkontrolujeme, zda je výsledek vektor.

    str(rozdeleneHodnoty)
    List of 1
     $ : chr [1:5] "Tea" "is" "better" "than" ...
  4. Jedná se o list; je potřeba ho změnit na vektor.

    rozdeleneHodnoty <- unlist(rozdeleneHodnoty)
  5. Zontrolujeme, zda se jedná o vektor s počtem hodnot > 1.

    str(rozdeleneHodnoty)
     chr [1:5] "Tea" "is" "better" "than" "coffee"

Úloha 2

Vytvořte list, který bude obsahovat informace o vašem oblíbeném filmu; jeho název, kdo jej režiséroval, kdy byl vydán, alespoň tři jména herců a hereček, kteří v něm hráli, na jaké ceny byl nominován a jaké společnosti se angažovaly jako jeho producenti. Jakmile budete mít list vytvořený, připojte do seznamu herců/hereček Zaphoda Beeblebroxe.

  1. Vytvoříme list podle zadání.

    film <- list(jmeno = "The Adventures of Priscilla, Queen of the Desert",
                 rezie = "Stephan Elliott",
                 rok = 1994,
                 obsazeni = c("Hugo Weaving", "Guy Pearce", "Terence Stamp"),
                 oceneni = c("Academy Awards", "BAFTA"),
                 producenti = "Michael Hamlyn and Al Clark"); film
    $jmeno
    [1] "The Adventures of Priscilla, Queen of the Desert"
    
    $rezie
    [1] "Stephan Elliott"
    
    $rok
    [1] 1994
    
    $obsazeni
    [1] "Hugo Weaving"  "Guy Pearce"    "Terence Stamp"
    
    $oceneni
    [1] "Academy Awards" "BAFTA"         
    
    $producenti
    [1] "Michael Hamlyn and Al Clark"
  2. Připojíme hodnotu "Zaphod Beeblebrox".

    film <- within(film,
           obsazeni <- c(obsazeni, "Zaphod Beeblebrox")); film
    $jmeno
    [1] "The Adventures of Priscilla, Queen of the Desert"
    
    $rezie
    [1] "Stephan Elliott"
    
    $rok
    [1] 1994
    
    $obsazeni
    [1] "Hugo Weaving"      "Guy Pearce"        "Terence Stamp"    
    [4] "Zaphod Beeblebrox"
    
    $oceneni
    [1] "Academy Awards" "BAFTA"         
    
    $producenti
    [1] "Michael Hamlyn and Al Clark"

    To je ale nějak komplikované, nešlo by to vyřešit jednodušeji?

  3. Zkusme si připojit hodnotu "Ford Prefect" způsobem, který vám byl doporučován v materiálech, co jste na webu našli.

    film$obsazeni <- c(film$obsazeni, "Ford Prefect")
    film
    $jmeno
    [1] "The Adventures of Priscilla, Queen of the Desert"
    
    $rezie
    [1] "Stephan Elliott"
    
    $rok
    [1] 1994
    
    $obsazeni
    [1] "Hugo Weaving"      "Guy Pearce"        "Terence Stamp"    
    [4] "Zaphod Beeblebrox" "Ford Prefect"     
    
    $oceneni
    [1] "Academy Awards" "BAFTA"         
    
    $producenti
    [1] "Michael Hamlyn and Al Clark"

Připojení jde provést pomocí práce s výběrem hodnot - takzvanou indexací. A přesně na to se tuto hodinu podíváme :).

Úloha 3

Kolik odlišných hodnot je v následujícím vektoru?

c(3, 2, 7, 45, 2, 6, 11, 7,
  90, 76, 4, 3, 46, 45, 7,
  89, 6, 45, 1, 55, 12, 90,
  2, 67, 2, 8, 7, 4, 34, 6)
 [1]  3  2  7 45  2  6 11  7 90 76  4  3 46 45  7 89  6 45  1 55 12 90  2 67  2
[26]  8  7  4 34  6
  1. Vytvořme si vektor obsahující hodnoty, které chceme analyzovat.

    seznam <- c(3, 2, 7, 45, 2, 6, 11, 7,
      90, 76, 4, 3, 46, 45, 7,
      89, 6, 45, 1, 55, 12, 90,
      2, 67, 2, 8, 7, 4, 34, 6); seznam
     [1]  3  2  7 45  2  6 11  7 90 76  4  3 46 45  7 89  6 45  1 55 12 90  2 67  2
    [26]  8  7  4 34  6
  2. Ke zjištění, kolik odlišných/unikátních hodnot je v daném vektoru, můžeme dojít několika cestami. Jako první si ukážeme využití faktorizace.

    seznam2 <- as.factor(seznam) #prevedeme na faktory
    str(seznam2) #jaka je nyni struktura?
     Factor w/ 17 levels "1","2","3","4",..: 3 2 6 11 2 5 8 6 17 15 ...
    levels(seznam2) #jake mame kategorie
     [1] "1"  "2"  "3"  "4"  "6"  "7"  "8"  "11" "12" "34" "45" "46" "55" "67" "76"
    [16] "89" "90"
    length(levels(seznam2)) #...a kolik jich je?
    [1] 17
    nlevels(seznam2) #a co kdyz si to chceme napsat dedikovanou funkci?
    [1] 17
  3. Můžeme k tomu ale použít i specifickou funkci unique.

    unique(seznam) #vyber pouze unikatni hodnoty
     [1]  3  2  7 45  6 11 90 76  4 46 89  1 55 12 67  8 34
    length(unique(seznam)) #kolik jich je?
    [1] 17

Indexace / výběr specifických dat

Výběr specifických dat je jedna ze základních funkcí R; není pro to nutně třeba potřeba používat balíčky. Balíčky nám celý proces ovšem značně usnadní.

Vyhledávání pomocí [ ]

objekt ve kterém se vyhledává[pozice či charakteristiky vyhledávané hodnoty ve všech dimenzích]

  • objekt o jedné dimenzi: objekt[informace pro výběr hodnoty]

  • objekt o dvou dimenzích: objekt[řádek, sloupec]

  • objekt o třech dimenzích: objekt[řádek, sloupec, matice]

  • …

Vektory

Jak víme, vektory mají pouze jednu dimenzi. Proto k definování pozice hodnot(y) stačí pouze jeden údaj.

vektor <- c(a = 558, b = 67846, c = 8797); vektor
    a     b     c 
  558 67846  8797 
vektor[3] #treti pozice ve vektoru
   c 
8797 
vektor["c"] #hodnota pojmenovaná jako c
   c 
8797 

Proč se u jména hodnoty používají uvozovky?

Bez použití uvozovek bychom R říkali, ať vektor indexuje pomocí informací uložených v objektu c. I to je ovšem možné; objekty samotné v sobě mohou obsahovat informace v potřebném formátu.

cislo <- 2
pismeno <- "a"
vektor
    a     b     c 
  558 67846  8797 
vektor[cislo]
    b 
67846 
vektor[pismeno]
  a 
558 

Je možné vybírat i více hodnot najednou. Jakým způsobem byste vybrali první a třetí hodnotu z objektu vektor?

vektor[c(1, 3)] #porad do vektoru vkladame pouze jeden "objekt"
   a    c 
 558 8797 

Pro výběr více hodnot nepoužíváme čárku!

Na základě tohoto principu lze hodnoty vybírat pomocí různých způsobů:

vektor[1:2] #prvni az druha hodnota
    a     b 
  558 67846 
vektor[-1] #vsechny hodnoty krome prvni (pozor: lze jen s cislem poradi!)
    b     c 
67846  8797 
Lze vybírat i pomocí charakteristik jednotlivých hodnot?

Nyní dokážeme vybrat hodnoty podle čísla jejich pozice. Co když chceme ale vybrat hodnoty podle jejich charakteristik?

vektor[vektor < 600] = vyber z objektu vektor ty hodnoty, které splňují podmínku, že jsou menší než 600

vektor < 600 #pouze a je TRUE
    a     b     c 
 TRUE FALSE FALSE 
#vektor[vektor < 600]) je proto defakto vektor["a"]

Proč nemůžeme jednoduše napsat vektor[< 600]?

Při < 600 chybí levá strana; co je menší než 600?

Pro výběr se používají čistě logické hodnoty!

Výběr defacto znamená, že se R předá vektor s hodnotami TRUE/FALSE o tom, zda má být hodnota na dané pozici do výběru zařazena.

vektor < 600 #TRUE, FALSE, FALSE
    a     b     c 
 TRUE FALSE FALSE 
vektor[vektor < 600]
  a 
558 
vektor[c(TRUE, FALSE, FALSE)]
  a 
558 

K výběru lze samozřejmě použít i ostatní operátory.

#vyber ty hodnoty ktere jsou presne 67846
vektor[vektor == 67846]
    b 
67846 
#vyber hodnoty ktere jsou vetsi nez 600 a zaroven mensi nez 50 000
vektor[vektor > 600 & vektor < 50000]
   c 
8797 

Vybírání specifických hodnot nemusíme ale používat pouze k jejich vyhledávání. Můžeme pomocí tohoto principu i přiřazovat a přepisovat jednotlivé hodnoty.

x1 <- 1:20; x1
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
length(x1) #kolik hodnot je ulozeno v x1?
[1] 20

Pokud chceme, aby 2. hodnota x1 byla 55, jak ji můžeme přidat?

x1[2] <- 55; x1
 [1]  1 55  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

Co když ale chceme, aby číslo 55 bylo na pozici 42?

x1[42] #v x1 v tuto chvili zadna hodnota na pozici 42 neni
[1] NA
x1[42] <- 55; x1
 [1]  1 55  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 NA NA NA NA NA
[26] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 55

Procvičení

  1. Vyber z následujícího vektoru poslední čtyři hodnoty

  2. Vyber všechny hodnoty z vektoru krom té se jménem ageGroup. Nevypisuj ručně nový vektor, použij k výběru funkce či operátory.

Samostatné cvičení

Vyberte z čísel 1878 až 2324 pouze ty, které jsou dělitelné třemi. Kolik jich je?

Nápověda

Zapřemýšlejte se nad tím, co to znamená, že je číslo dělitelné třemi. Je možné si tuto charakteristiku ověřit nějakým operátorem?

Nezapomeňte, že indexace podle podmínek defacto není nic jiného než výběr hodnot pomocí TRUE a FALSE.

Řešení

Vyber z čísel 1878 až 2324 pouze ty, které jsou dělitelné třemi. Kolik jich je?

  1. Pro jednodušší zacházení s čísly si je uložíme jako proměnnou.

    cisla <- 1878:2324
  1. Co znamená, že je číslo dělitelné třemi?

    Po dělení třemi po něm nezůstane žádný zbytek. Jak toto v R zjistíme?

    cisla %% 3
      [1] 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
     [38] 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
     [75] 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
    [112] 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
    [149] 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
    [186] 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
    [223] 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
    [260] 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
    [297] 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
    [334] 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
    [371] 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
    [408] 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
    [445] 0 1 2
  1. Chceme vybrat pouze ta čísla, která jsou dělitelná třemi -> nemají žádný zbytek -> zbytek je 0. Jak to provedeme?

    cisla %% 3 == 0
      [1]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [13]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [25]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [37]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [49]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [61]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [73]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [85]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
     [97]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [109]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [121]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [133]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [145]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [157]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [169]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [181]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [193]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [205]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [217]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [229]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [241]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [253]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [265]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [277]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [289]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [301]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [313]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [325]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [337]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [349]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [361]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [373]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [385]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [397]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [409]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [421]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [433]  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
    [445]  TRUE FALSE FALSE
  1. Máme v tuto chvíli sekvenci TRUE/FALSE hodnot, které popisují vlastnosti jednotivých hodnot ve vektoru cisla. Jak ji využijeme k indexaci?

    cisla[cisla %% 3 == 0]
      [1] 1878 1881 1884 1887 1890 1893 1896 1899 1902 1905 1908 1911 1914 1917 1920
     [16] 1923 1926 1929 1932 1935 1938 1941 1944 1947 1950 1953 1956 1959 1962 1965
     [31] 1968 1971 1974 1977 1980 1983 1986 1989 1992 1995 1998 2001 2004 2007 2010
     [46] 2013 2016 2019 2022 2025 2028 2031 2034 2037 2040 2043 2046 2049 2052 2055
     [61] 2058 2061 2064 2067 2070 2073 2076 2079 2082 2085 2088 2091 2094 2097 2100
     [76] 2103 2106 2109 2112 2115 2118 2121 2124 2127 2130 2133 2136 2139 2142 2145
     [91] 2148 2151 2154 2157 2160 2163 2166 2169 2172 2175 2178 2181 2184 2187 2190
    [106] 2193 2196 2199 2202 2205 2208 2211 2214 2217 2220 2223 2226 2229 2232 2235
    [121] 2238 2241 2244 2247 2250 2253 2256 2259 2262 2265 2268 2271 2274 2277 2280
    [136] 2283 2286 2289 2292 2295 2298 2301 2304 2307 2310 2313 2316 2319 2322
  1. Vybrali jsme v tuto chvíli všechny čísla z 1878 až 2324, které jsou dělitelné třemi. Jak zjistíme, kolik jich je?

    length(cisla[cisla %% 3 == 0]) #149
    [1] 149

Výpočet samozřejmě můžeme provést i bez vytváření proměnných.

length((1878:2324)[1878:2324 %% 3 == 0])
[1] 149
#pozor! pri tomto postupu je treba dat sekvenci do zavorky
  #r nemilosrdne dela vyber hned z nejblizsi hodnoty u hranate zavorky

Matice

Matice narozdíl od vektoru mají již dvě dimenze; řádky a sloupce. Pro výběr nám tak už nestačí pouze jedno číslo.

Jak obě dimenze do výběru zapíšu? Vzpomeňte si na přehled ve Vyhledávání pomocí [ ]

matice <- matrix(10:33, nrow = 4); matice
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   10   14   18   22   26   30
[2,]   11   15   19   23   27   31
[3,]   12   16   20   24   28   32
[4,]   13   17   21   25   29   33
matice[1,3] #prvni radek treti sloupec
[1] 18
matice[2,5] #druhy radek, paty sloupec
[1] 27
matice[ ,1] #vsechny hodnoty v prvnim sloupci
[1] 10 11 12 13
matice[2, ] #vsechny hodnoty v druhem radku
[1] 11 15 19 23 27 31
matice[1:3,5:6] #prvni az treti radek a paty az sesty sloupec
     [,1] [,2]
[1,]   26   30
[2,]   27   31
[3,]   28   32

Můžeme k výběru používat i jména sloupců a řádků?

dim(matice) #4 radky 6 sloupcu
[1] 4 6
dimnames(matice) <- list(LETTERS[1:4], letters[1:6])
#LETTERS a letters jsou v baseR ulozene objekty
matice
   a  b  c  d  e  f
A 10 14 18 22 26 30
B 11 15 19 23 27 31
C 12 16 20 24 28 32
D 13 17 21 25 29 33
matice["A", "c"] #radek A, sloupec c
[1] 18
matice["B", 3] #radek B, treti sloupec
[1] 19
matice[,c("a", "c", "d")] #vsechny radky a sloupce a, c, d
   a  c  d
A 10 18 22
B 11 19 23
C 12 20 24
D 13 21 25

Při výběru hodnot z matice používáme totožné principy jako při výběru z vektorů; jen se musí pro výběr definovat více dimenzí.1

Výběr podle specifických hodnot

Stejným způsobem, jako můžeme vybírat specifické hodnoty u vektoru, totéž můžeme provést i u matice.

matice #zobrazeni pro prehled
   a  b  c  d  e  f
A 10 14 18 22 26 30
B 11 15 19 23 27 31
C 12 16 20 24 28 32
D 13 17 21 25 29 33
#vyber vsechny radky, ktere maji v druhem sloupci vetsi hodnotu nez 15
matice[matice[,2] > 15,]
   a  b  c  d  e  f
C 12 16 20 24 28 32
D 13 17 21 25 29 33

Z kódu je zřejmé, že budeme vybírat všechny sloupce. Ale co znamená matice[,2] > 15 v řádcích?

matice[,2] #vyber hodnoty vsech radku, druhy sloupec
 A  B  C  D 
14 15 16 17 
matice[,2] > 15 #ktere z techto radku maji hodnotu vyssi jak 15?
    A     B     C     D 
FALSE FALSE  TRUE  TRUE 

Pomocí tohoto kódu si vybereme pouze ty řádky, které splňují stanovenou podmínku.

matice[matice[,2] > 15,]
   a  b  c  d  e  f
C 12 16 20 24 28 32
D 13 17 21 25 29 33
matice[c("C", "D"),] #totozny vysledek
   a  b  c  d  e  f
C 12 16 20 24 28 32
D 13 17 21 25 29 33

Třeba jasně definovat podmínky pro všechny sloupce a řádky

Přemýšlejte nad tím takto: musí R vždy říct, jestli tam má každý sloupec či řádek zařadit; zda má být součástí výběru (TRUE).

Ukázka

matice[c("C", "D"),]
   a  b  c  d  e  f
C 12 16 20 24 28 32
D 13 17 21 25 29 33
matice[c(FALSE, FALSE, TRUE, TRUE),]
   a  b  c  d  e  f
C 12 16 20 24 28 32
D 13 17 21 25 29 33

Proč nemůžeme jednoduše použít následující kód?

Huh, proč se nám vybrala celá matice?

"B" > 15 #porovnavame zda je text vetsi nez pismeno
[1] TRUE
  1. Dojde k nucené konverzi do charakteru, aka

    "B" > "15"
    [1] TRUE

    Proč ale?

  1. Jednotlivá písmena jsou v R uložena podle abecedy; B je tedy tak na druhé pozici.

    "2" > "15"
    [1] TRUE

Jak to že je ale 2 > 15?

  1. Neporovnáváme čísla, ale písmena - R hodnotí text “15” na základě prvního symbolu. A 2 > 1 = TRUE
  1. Vznikne nám proto defakto následující pokyn:

    matice[TRUE, ]
       a  b  c  d  e  f
    A 10 14 18 22 26 30
    B 11 15 19 23 27 31
    C 12 16 20 24 28 32
    D 13 17 21 25 29 33

    Pro to, aby výběr matice fungoval, tak je potřeba, aby se definovaly všechny řádky. Zde jsme ale dodali pouze jednu hodnotu. Víme ale, že R si v některých případech dokáže hodnoty samo doplnit, viz sekce Tvorba matice v druhé lekci.

  1. Ve výsledku jsme R zadali následující kód:

    matice[c(TRUE, TRUE, TRUE, TRUE), ] #aka vyber vsechny radky
       a  b  c  d  e  f
    A 10 14 18 22 26 30
    B 11 15 19 23 27 31
    C 12 16 20 24 28 32
    D 13 17 21 25 29 33

Proč vám toto celé říkám?

  • Nemůžete počítat s tím, že když něco “pokazíte”, nutně vám vyskočí error.

  • R má spoustu funkcí a pokynů, i já někdy narazím na mně zcela nové věci

  • Kontrolujte si jednotlivé pokyny, které skládáte dohromady!

Procvičení

  1. Vyber z prvního řádku matice ty sloupce, které mají hodnoty větší jak 25 nebo menší jak 15.

  2. Vyber ty řádky matice, které mají ve sloupci c hodnotu přesně 20.

Samostatné cvičení

Zkušební datasety v R

V R je nainstalováno několik datasetů určených k zkoušení si funkcí a celkovému hraní si. Datasety HairEyeColor, který budeme v následujícím procvičení používat, je právě jeden z nich. Pro jeho používání není potřeba je jakkoliv nahrávat či ukládat jako proměnné. Stačí si pouze zavolat jeho jméno.

Kolik studentek, které se účastnily měření, má blond vlasy a zelené oči? Použijte dataset HairEyeColor.

Vybírání dimenzí

Pokud si nejste jisti jak postupovat, podívejte se znovu na poslední téma co jsme probírali a především na základ v Vyhledávání pomocí [ ] ;)

Řešení

Kolik studentek, které se účastnily měření, má blond vlasy a zelené oči?

  1. Nejdříve se podíváme na to, co je dataset HairEyeColor zač; jakou má strukturu? Jak vypadá?.

    str(HairEyeColor) #jaka je struktura
     'table' num [1:4, 1:4, 1:2] 32 53 10 3 11 50 10 30 10 25 ...
     - attr(*, "dimnames")=List of 3
      ..$ Hair: chr [1:4] "Black" "Brown" "Red" "Blond"
      ..$ Eye : chr [1:4] "Brown" "Blue" "Hazel" "Green"
      ..$ Sex : chr [1:2] "Male" "Female"
    head(HairEyeColor) #zobraz mi prvnich 6 radku
    , , Sex = Male
    
           Eye
    Hair    Brown Blue Hazel Green
      Black    32   11    10     3
      Brown    53   50    25    15
      Red      10   10     7     7
      Blond     3   30     5     8
    
    , , Sex = Female
    
           Eye
    Hair    Brown Blue Hazel Green
      Black    36    9     5     2
      Brown    66   34    29    14
      Red      16    7     7     7
      Blond     4   64     5     8
    dim(HairEyeColor) #jake jsou dimenze objektu
    [1] 4 4 2
    is.array(HairEyeColor) #nejedna se o array?
    [1] TRUE
  1. Jedná se o array, takže je potřeba definovat výběr ve všech dimenzích.

    HairEyeColor["Blond", "Green", "Female"]
    [1] 8

Data frame

Data frame a matice mají stejný počet dimenzí; data frame tak můžeme indexovat stejným způsobem jako matici.

vek <- c(27,35,30,47,42)
sex <- c("female","male","male","female","female")
strana <-c("sin","sin","dx","dx","dx")
ID <- c("SC_001", "SC_007", "SC_013", "SC_014", "SC_020")
df <- data.frame(vek, strana, sex, row.names = ID); df
       vek strana    sex
SC_001  27    sin female
SC_007  35    sin   male
SC_013  30     dx   male
SC_014  47     dx female
SC_020  42     dx female
df[1, 3] #prvni radek, treti sloupec
[1] "female"
df["SC_020", 1] #radek jmenem SC_020, prvni sloupec
[1] 42
#radky ktere maji v druhem sloupci hodnotu "sin" a vsechny sloupce
df[df[,2] == "sin",]
       vek strana    sex
SC_001  27    sin female
SC_007  35    sin   male

Výběr hodnot specifického sloupce

Data frame má narozdíl od matice ovšem jednu velkou výhodu; můžeme indexovat přímo pomocí jmen sloupců. Co to znamená?

#vyber sloupec strana
df["strana"]
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx

Výběr celého sloupce znamená i výběr všech řádků

Proč zde nemusíme použít čárku? R defacto říkáme “vyber celý objekt jménem strana, včetně jeho struktury a pojmenování”. A celý sloupec strana obsahuje hodnoty pro každý řádek.

Můžu si takto zavolat i řádky?

R automaticky usuzuje že data frame je poskládaný tak, že jednotlivá měření/vzorky/pozorování jsou zapsaná v řádcích, nikoliv ve sloupcích - jedná se o takzvaný long formát dat. To znamená, že usuzuje, že jednotlivé vektory, ze kterých se data frame skládá, budou sloupce.

Více o long formátu a proč je dobré ho používat si řekneme během příští lekce při probírání konceptu “tidy data”.

Past vedle pasti

Možná si myslíte, že v tuto chvíli znáte veškeré základní způsoby indexace v base R. Na vše samozřejmě existují “vyjímky”.

df["strana"]
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx
df[2]
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx
identical(df["strana"], df[2])
[1] TRUE

Při výběru pouze jedné hodnoty u data frame R automaticky usoudí, že se jedná o výběr sloupce na této pozici.

df[2] #vyber druhy sloupec podle poradi
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx
df["strana"] #vyber druhy sloupec podle jmena
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx
df[ ,2] #vyber druhy sloupec, vsechny radky
[1] "sin" "sin" "dx"  "dx"  "dx" 
df[ ,1:2] #vyber prvni a druhy sloupec, vsechny radky
       vek strana
SC_001  27    sin
SC_007  35    sin
SC_013  30     dx
SC_014  47     dx
SC_020  42     dx

Proč nám výsledky vycházejí někdy jako vektor a jindy jako data frame?

Jak bylo zmíněno v sekci Výběr celého sloupce znamená i výběr všech řádků, výběrem sloupce vybíráme objekt, který tvoří data frame - nikoliv pouze hodnoty. R proto vrátí část data frame, včetně struktur, popisků a všeho - vrátí se nám proto data frame o jednom sloupci.

df["vek"]
       vek
SC_001  27
SC_007  35
SC_013  30
SC_014  47
SC_020  42
df[2]
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx

Když ovšem provedeme výběr definicí df[ ,"strana"], tak dochází k jinému pokynu. R totiž říkáme následující:

Vyber hodnoty v druhém sloupci, a to pro všechny řádky.

A co je výsledkem řady hodnot? Vektor.

df[ ,"vek"]
[1] 27 35 30 47 42
df[ ,2]
[1] "sin" "sin" "dx"  "dx"  "dx" 

Je ovšem možné přinutit R, aby si zachovalo původní data frame strukturu.

df[ ,"vek", drop = FALSE]
       vek
SC_001  27
SC_007  35
SC_013  30
SC_014  47
SC_020  42
df[ ,2, drop = FALSE]
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx

Argument drop = FALSE nám totiž nuceně udrží i výběr takovéhoto typu jako data frame.

Nezapomeňte, že indexace je defacto typ funkce!

Provádíme akci na základě určitých parametrů, která provede změny na datech.

Podívejte se v nápovědě na funkci extract ;).

df[ ,2, drop = TRUE]
[1] "sin" "sin" "dx"  "dx"  "dx" 
df[ ,2, drop = FALSE]
       strana
SC_001    sin
SC_007    sin
SC_013     dx
SC_014     dx
SC_020     dx
df[ ,2] #argument defaultne urceny jako TRUE
[1] "sin" "sin" "dx"  "dx"  "dx" 

Proč nám při výběru hodnot z více sloupců a libovolného počtu řádku ovšem opět vznikne data frame?

df[2,c("vek", "strana")]
       vek strana
SC_007  35    sin
df[ ,c("vek", "strana")]
       vek strana
SC_001  27    sin
SC_007  35    sin
SC_013  30     dx
SC_014  47     dx
SC_020  42     dx

Nápověda: výsledek nám může vrátit hodnoty různého datového typu

Nelze vrátit vektor, který obsahuje hodnoty v jiné podobě než jednodimenzionálně poskládané za sebou. Stejně tak matice nemůže obsahovat více data typů.

Jediným možným řešením je proto strukturovat data jako data frame.

Co znamená [[x]]?

Někdy se můžete setkat s tím, že údaj, pomocí kterého se indexuje, je zapsaný v dvojtých hranatých závorkách. Co to znamená?

df[["strana"]] #vyber mi prevek s jmenem "strana"
[1] "sin" "sin" "dx"  "dx"  "dx" 
df[[2]] #vyber mi druhy prvek
[1] "sin" "sin" "dx"  "dx"  "dx" 

Dvojité hranaté závorky nám říkají; vyber mi prvek x a vše, co se v něm nachází.

Jednotlivé prvky data frame jsou vektory, proto nám indexace vrátí vektor hodnot.

Seznam způsobů indexace data frame a jejich výsledků

Způsob indexace Výsledek
df[,"col"] vektor
df[,"col",drop = FALSE] data frame
df["col"] data frame
df[["col"]] vektor
df$col vektor

Procvičení

  1. Vyber první sloupec v data frame df jako vektor i data frame.

  2. Vyber první a poslední řádek data frame df.

Vyhledávání pomocí $

Při vytváření indexování specificky pojmenovaného sloupce se někdy používá symbol $.

#vyber hodnoty sloupce strana
df[,"strana"]
[1] "sin" "sin" "dx"  "dx"  "dx" 
df$strana
[1] "sin" "sin" "dx"  "dx"  "dx" 

symbol $ provede výběr hodnot ze specifické komponenty datové struktury podle jejího názvu

list/data frame ve kterém se hledá$název objektu, který ho tvoří

Jen tak ze zvědavosti, lze tento typ indexace použít i u matice?

Nápověda: jaká je definice data frame a matice?

Zatímco matice jsou defacto pouze hodnoty jednoho data typu poskládané do řádků a sloupců, které mohou být pojmenované, data frame je objekt složený z jiných objektů.

Jaká je struktura matice?

str(matice)
 int [1:4, 1:6] 10 11 12 13 14 15 16 17 18 19 ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:4] "A" "B" "C" "D"
  ..$ : chr [1:6] "a" "b" "c" "d" ...

Jaká je struktura data frame?

str(df)
'data.frame':   5 obs. of  3 variables:
 $ vek   : num  27 35 30 47 42
 $ strana: chr  "sin" "sin" "dx" "dx" ...
 $ sex   : chr  "female" "male" "male" "female" ...

Kdy použijeme výběr pomocí $?

Kdykoliv, kdy potřebujeme pracovat s čistými hodnotami, nikoliv celou datovou strukturou.

Příkladem může být jak čistá indexace, ale i přepisování, nebo třeba i doplňování dalších hodnot.

Několik z možností si probereme v následující části.

Indexace

#vyber radky, ktere maji ve sloupci "vek" hodnotu > 30
df[df$vek > 30, ]
       vek strana    sex
SC_007  35    sin   male
SC_014  47     dx female
SC_020  42     dx female

Jak to funguje? Totožně jako u jakékoliv jiné indexace; výběrem TRUE a FALSE hodnot.

df$vek #vektor hodnot
[1] 27 35 30 47 42
df$vek > 30 #jsou hodnoty vetsi nez 30
[1] FALSE  TRUE FALSE  TRUE  TRUE
df[df$vek > 30, ] #vyber radky dle tohoto vektoru
       vek strana    sex
SC_007  35    sin   male
SC_014  47     dx female
SC_020  42     dx female
df[c(FALSE, TRUE, FALSE, TRUE, TRUE), ] #dukaz vyberu
       vek strana    sex
SC_007  35    sin   male
SC_014  47     dx female
SC_020  42     dx female

Zjištění pořadí řádku

Co když bychom chtěli ale znát pořadí (číslo) řádku?

Funkce which zjistí, pro které pozice řádků v logickém vektoru či array platí, že jsou pravdivé.

df$vek > 30
[1] FALSE  TRUE FALSE  TRUE  TRUE
which(df$vek > 30)
[1] 2 4 5

Další možnost je například přepis hodnot.

#ve sloupci "strana" prepis hodnoty nasledovne:
  #hodnoty "sin" prepis jako "leva"
  #nasledne hodnoty "dx" prepis jako "prava"
df$strana[df$strana == "sin"] <- "leva"
df
       vek strana    sex
SC_001  27   leva female
SC_007  35   leva   male
SC_013  30     dx   male
SC_014  47     dx female
SC_020  42     dx female

Co se v tomto kódu provede?

df$strana #vektor hodnot
[1] "leva" "leva" "dx"   "dx"   "dx"  
df$strana == "dx" #plati na hodnoty tato podminka?
[1] FALSE FALSE  TRUE  TRUE  TRUE
df$strana[df$strana == "dx"] #vyber ty hodnoty, pro ktere je podminka TRUE
[1] "dx" "dx" "dx"
df$strana[df$strana == "dx"] <- "prava" #prepis tyto hodnoty uvnitr data frame "df"
df
       vek strana    sex
SC_001  27   leva female
SC_007  35   leva   male
SC_013  30  prava   male
SC_014  47  prava female
SC_020  42  prava female

Nakonec si vyzkoušíme i přiřazování dalších hodnot.

#k hodnotam ze sloupce "vek" pridej cisla od 1 do 10
c(df$vek, 1:10)
 [1] 27 35 30 47 42  1  2  3  4  5  6  7  8  9 10

Přiřazováním ale můžeme i vytvářet celé další sloupce.

dim(df)
[1] 5 3
df$score <- 1:nrow(df)
df
       vek strana    sex score
SC_001  27   leva female     1
SC_007  35   leva   male     2
SC_013  30  prava   male     3
SC_014  47  prava female     4
SC_020  42  prava female     5
dim(df)
[1] 5 4

Co jsme zde provedli?

  • dim(df): kolik dimenzí má df

  • 1:nrow(df): vektor, který má v sobě tolik hodnot co df řádků

  • df$score <- 1:nrow(df): ulož vektor jako hodnoty ve sloupci score

Procvičení

Zkušební datasety v balíčku dplyr

V balíčku dplyr je nainstalováno několik datasetů určených k zkoušení si funkcí a celkovému hraní si, obdobně jako v baseR. Dataset storms, který budeme v následujícím procvičení používat, je právě jedním z nich. Pro jejich používání je potřeba mít balíček načtený. Dataset iris je součástí baseR.

  1. Jak průměrně rychlé byly větry (wind) v roce, kdy jste se narodili (year)? Použijte dataset dplyr::storms.
  1. Vyber z datasetu iris všechny měření, kdy délka kalichu květiny (Sepal.Length) je menší než 5, nebo jejich šířka (Sepal.Width) je větší než 3.5 a zároveň se jedná o druh (Species) setosa.
  1. Jaká je průměrná délka okvětních lístků (Petal.Lenght) pro druh setosa, poté co jsme provedli filtrování v předchozím cvičení?

Samostatné cvičení

Nahrajte si data uložená v souboru bikes.RData. Ten obsahuje přehled testování motorek, kdy každý stroj dostal určitý počet bodů za hodnocení rychlosti (speed), pohodlnosti na vzdálenost (dist) a pak ještě celkové hodnocení od nezávislého odborníka (rating), kdy 1 je nejlepší, 5 je nejhorší.

  1. Vyberte motorky, které měly každá dohromady počet bodů z hodnocení speed a dist sice celkem menší než 50, ale i tak dostaly rating lepší než 3. Vypište jejich názvy.

Bonus: Přepiš hodnoty ve sloupci dist v tomto výběru tak, že pokud je hodnota menší jak 20, bude nahrazena slovy “pod dvacet”, pokud bude větší nebo rovno 20, bude nahrazena slovy “dvacet +”.

Řešení úlohy 1)

Vyberte motorky, které měli počet bodů z obou hodnocení dohromady sice menší než 50, ale i tak dostaly rating lepší než 3. Vypište jejich názvy.

  1. Podíváme se na strukturu datového objektu bikes a necháme si vyjet prvních několik řádků. Vidíme, že se jedná o data frame, takže k vyhledávání můžeme používat přímo názvy sloupců.

    str(bikes)
    'data.frame':   50 obs. of  3 variables:
     $ speed : num  4 4 7 7 8 9 10 10 10 11 ...
     $ dist  : num  2 10 4 22 16 10 18 26 34 17 ...
     $ rating: int  5 5 2 2 2 1 4 2 3 3 ...
    head(bikes)
            speed dist rating
    bike_01     4    2      5
    bike_02     4   10      5
    bike_03     7    4      2
    bike_04     7   22      2
    bike_05     8   16      2
    bike_06     9   10      1
  1. Vyber ty řádky, kde součet z hodnot ve sloupcích speed a dist je < 50, a zároveň hodnota ve sloupci rating je < 3.

    bikes[bikes$speed + bikes$dist < 50 & bikes$rating < 3,]
            speed dist rating
    bike_03     7    4      2
    bike_04     7   22      2
    bike_05     8   16      2
    bike_06     9   10      1
    bike_08    10   26      2
    bike_25    15   26      2
    bike_27    16   32      1
    bike_29    17   32      2
  1. Pro snažší práci s tímto výběrem si ho pojmenujeme a uložíme.

    divneHodnoceni <- bikes[bikes$speed + bikes$dist < 50 & bikes$rating < 3,]
  1. Vypíšeme si názvy řádků tohoto výběru.

    rownames(divneHodnoceni)
    [1] "bike_03" "bike_04" "bike_05" "bike_06" "bike_08" "bike_25" "bike_27"
    [8] "bike_29"

Řešení bonusové úlohy

Přepiš hodnoty ve sloupci dist v tomto výběru tak, že pokud je hodnota menší jak 20, bude nahrazena slovy “pod dvacet”, pokud bude větší nebo rovno 20, bude nahrazena slovy “dvacet +”.

  1. Vybereme hodnoty ze sloupce dist které jsou < 20 a přepíšeme je na charaktery “pod dvacet”.

    divneHodnoceni$dist[divneHodnoceni$dist < 20] <- "pod dvacet"
  1. Podíváme se na to, jaká je nyní struktura sloupce dist.

    str(divneHodnoceni$dist)
     chr [1:8] "pod dvacet" "22" "pod dvacet" "pod dvacet" "26" "26" "32" "32"
  1. Hodnoty se nuceně převedly na charaktery; není možné mít v jednom vektoru numeric a character hodnoty. Proto dále nemůžeme použít operátory > nebo <, ale použijeme místo toho operátory != aka “není přesně”.

    divneHodnoceni$dist[divneHodnoceni$dist != "pod dvacet"] <- "dvacet +"
    divneHodnoceni
            speed       dist rating
    bike_03     7 pod dvacet      2
    bike_04     7   dvacet +      2
    bike_05     8 pod dvacet      2
    bike_06     9 pod dvacet      1
    bike_08    10   dvacet +      2
    bike_25    15   dvacet +      2
    bike_27    16   dvacet +      1
    bike_29    17   dvacet +      2

List

Principy, které jsme se naučili na data frame, nyní můžeme použít k indexování listu.

lst <- list(osoba = list(jmeno = "Anna",
                         prijmeni = "Novotná"),
            povolani = "uklizecka",
            vek = 67); lst
$osoba
$osoba$jmeno
[1] "Anna"

$osoba$prijmeni
[1] "Novotná"


$povolani
[1] "uklizecka"

$vek
[1] 67
str(lst) #list, co ma v sobe tri dalsi objekty (jeden je take list)
List of 3
 $ osoba   :List of 2
  ..$ jmeno   : chr "Anna"
  ..$ prijmeni: chr "Novotná"
 $ povolani: chr "uklizecka"
 $ vek     : num 67

Jakým způsobem si můžeme z listu vybrat jednotlivé jeho části?

lst["vek"] #vyber objekt "vek"
$vek
[1] 67
str(lst["vek"]) #vraci list
List of 1
 $ vek: num 67
lst[["vek"]] #vyber co se nachazi v objektu "vek"
[1] 67
str(lst[["vek"]]) #vraci vektor
 num 67
lst$vek #vyber hodnoty z objektu "vek"
[1] 67
str(lst$vek) #vraci vektor
 num 67
lst[2] #vyber druhy objekt
$povolani
[1] "uklizecka"
lst[2:3] #vyber druhy az treti objekt
$povolani
[1] "uklizecka"

$vek
[1] 67

Co když ale nevybíráme jednoduchou část listu, jako třeba vektor? Co když se jedná o další list?

lst["osoba"] #vyber objekt "osoba"
$osoba
$osoba$jmeno
[1] "Anna"

$osoba$prijmeni
[1] "Novotná"
str(lst["osoba"])
List of 1
 $ osoba:List of 2
  ..$ jmeno   : chr "Anna"
  ..$ prijmeni: chr "Novotná"
lst[["osoba"]] #vyber obsah objektu "osoba"
$jmeno
[1] "Anna"

$prijmeni
[1] "Novotná"
str(lst[["osoba"]])
List of 2
 $ jmeno   : chr "Anna"
 $ prijmeni: chr "Novotná"
lst$osoba #vyber obsah objektu jmenem "osoba"
$jmeno
[1] "Anna"

$prijmeni
[1] "Novotná"
str(lst$osoba)
List of 2
 $ jmeno   : chr "Anna"
 $ prijmeni: chr "Novotná"

A co když nechceme vybrat pouze ten list, ale přímo hodnoty v něm?

lst$osoba$jmeno
[1] "Anna"
lst[["osoba"]][["prijmeni"]]
[1] "Novotná"

Rozdíl mezi [[]] a $

Možná si říkáte, proč vůbec potřebujeme tyto dva druhy indexace. Nedělá to přeci jen to samé?

identical(lst[["osoba"]], lst$osoba)
[1] TRUE

Důležité je se dívat na to, jakým způsobem vkládáme do indexace.

  • indexace $ vždy volá specifický název

  • indexace [[]] volá to, co se jmenuje stejně jako hodnota uvnitř závorek

x <- "osoba"
lst[[x]] #vyber objekty co se jmenuji stejne jako obsah hodnoty x
$jmeno
[1] "Anna"

$prijmeni
[1] "Novotná"
lst$x #vyber objekt s nazvem x
NULL

Procvičení

  1. Přidejte paní Anně Novákové další povolání.

  2. Přidejte informace o jejích dvou dětech; každé ve vlastním listu se jménem a příjmením, dohromady pak ve společném listu “deti”.

Indexace pomocí funkcí balíčku dplyr

V tuto chvíli víme, na jakém principu funguje indexace v R, a s jakými symboly a způsoby provedení se můžete běžně setkat. Některé z těchto procesů indexace jsou ale dost krkolomné, nebo vyžadují od uživatele repetitivní psaní kódu.

Co kdyby existovalo něco… jednoduššího?

funkce dplyr::select

Vyber sloupce z data frame

select(název data frame, název sloupce)

select(bikes, speed)
        speed
bike_01     4
bike_02     4
bike_03     7
bike_04     7
bike_05     8
bike_06     9
bike_07    10
bike_08    10
bike_09    10
bike_10    11
bike_11    11
bike_12    12
bike_13    12
bike_14    12
bike_15    12
bike_16    13
bike_17    13
bike_18    13
bike_19    13
bike_20    14
bike_21    14
bike_22    14
bike_23    14
bike_24    15
bike_25    15
bike_26    15
bike_27    16
bike_28    16
bike_29    17
bike_30    17
bike_31    17
bike_32    18
bike_33    18
bike_34    18
bike_35    18
bike_36    19
bike_37    19
bike_38    19
bike_39    20
bike_40    20
bike_41    20
bike_42    20
bike_43    20
bike_44    22
bike_45    23
bike_46    24
bike_47    24
bike_48    24
bike_49    24
bike_50    25

To nevypadá tak impresivně, že? Vždyť to si mohu napsat i jako bikes$speed…

Co když ale máte sloupců na výběr podstatně více?

str(storms) #tibble "storms" ma 13 sloupcu
tibble [20,778 × 13] (S3: tbl_df/tbl/data.frame)
 $ name                        : chr [1:20778] "Amy" "Amy" "Amy" "Amy" ...
 $ year                        : num [1:20778] 1975 1975 1975 1975 1975 ...
 $ month                       : num [1:20778] 6 6 6 6 6 6 6 6 6 6 ...
 $ day                         : int [1:20778] 27 27 27 27 28 28 28 28 29 29 ...
 $ hour                        : num [1:20778] 0 6 12 18 0 6 12 18 0 6 ...
 $ lat                         : num [1:20778] 27.5 28.5 29.5 30.5 31.5 32.4 33.3 34 34.4 34 ...
 $ long                        : num [1:20778] -79 -79 -79 -79 -78.8 -78.7 -78 -77 -75.8 -74.8 ...
 $ status                      : Factor w/ 9 levels "disturbance",..: 7 7 7 7 7 7 7 7 8 8 ...
 $ category                    : num [1:20778] NA NA NA NA NA NA NA NA NA NA ...
 $ wind                        : int [1:20778] 25 25 25 25 25 25 25 30 35 40 ...
 $ pressure                    : int [1:20778] 1013 1013 1013 1013 1012 1012 1011 1006 1004 1002 ...
 $ tropicalstorm_force_diameter: int [1:20778] NA NA NA NA NA NA NA NA NA NA ...
 $ hurricane_force_diameter    : int [1:20778] NA NA NA NA NA NA NA NA NA NA ...
select(storms, lat, long, year, last_col())
# A tibble: 20,778 × 4
     lat  long  year hurricane_force_diameter
   <dbl> <dbl> <dbl>                    <int>
 1  27.5 -79    1975                       NA
 2  28.5 -79    1975                       NA
 3  29.5 -79    1975                       NA
 4  30.5 -79    1975                       NA
 5  31.5 -78.8  1975                       NA
 6  32.4 -78.7  1975                       NA
 7  33.3 -78    1975                       NA
 8  34   -77    1975                       NA
 9  34.4 -75.8  1975                       NA
10  34   -74.8  1975                       NA
# ℹ 20,768 more rows
select(storms, 1:4, starts_with(c("w", "h")))
# A tibble: 20,778 × 7
   name   year month   day  wind  hour hurricane_force_diameter
   <chr> <dbl> <dbl> <int> <int> <dbl>                    <int>
 1 Amy    1975     6    27    25     0                       NA
 2 Amy    1975     6    27    25     6                       NA
 3 Amy    1975     6    27    25    12                       NA
 4 Amy    1975     6    27    25    18                       NA
 5 Amy    1975     6    28    25     0                       NA
 6 Amy    1975     6    28    25     6                       NA
 7 Amy    1975     6    28    25    12                       NA
 8 Amy    1975     6    28    30    18                       NA
 9 Amy    1975     6    29    35     0                       NA
10 Amy    1975     6    29    40     6                       NA
# ℹ 20,768 more rows

funkce dplyr::filter

Vyber řádky na základě podmínky

filter(název data frame, podmínky hodnot ve sloupcích)

filter(storms, wind > 10,
       wind < 60,
       name %in% c("Jeanne", "Georges"),
       year == 1980,
       status != "disturbance")
# A tibble: 45 × 13
   name     year month   day  hour   lat  long status    category  wind pressure
   <chr>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>        <dbl> <int>    <int>
 1 Georges  1980     9     1     0  15.6 -38   tropical…       NA    30     1010
 2 Georges  1980     9     1     6  15.9 -39.4 tropical…       NA    30     1010
 3 Georges  1980     9     1    12  16.3 -40.8 tropical…       NA    30     1010
 4 Georges  1980     9     1    18  16.8 -42.1 tropical…       NA    30     1010
 5 Georges  1980     9     2     0  17.3 -43.7 tropical…       NA    30     1010
 6 Georges  1980     9     2     6  17.5 -45.7 tropical…       NA    30     1010
 7 Georges  1980     9     2    12  17.7 -48.1 tropical…       NA    30     1010
 8 Georges  1980     9     2    18  17.8 -50.3 tropical…       NA    30     1010
 9 Georges  1980     9     3     0  17.9 -52.4 tropical…       NA    30     1010
10 Georges  1980     9     3     6  18   -54.5 tropical…       NA    30     1010
# ℹ 35 more rows
# ℹ 2 more variables: tropicalstorm_force_diameter <int>,
#   hurricane_force_diameter <int>

A co kdybychom to spojili dohromady?

filtrovanaData <- filter(storms,
                         year %in% 1990:2000,
                         wind > 50,
                         !is.na(category), #neni NA
                         month == 6); filtrovanaData
# A tibble: 3 × 13
  name     year month   day  hour   lat  long status    category  wind pressure
  <chr>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>        <dbl> <int>    <int>
1 Allison  1995     6     4    12  24.7 -86.2 hurricane        1    65      987
2 Allison  1995     6     4    18  26.2 -86.2 hurricane        1    65      988
3 Allison  1995     6     5     0  27.6 -86.1 hurricane        1    65      988
# ℹ 2 more variables: tropicalstorm_force_diameter <int>,
#   hurricane_force_diameter <int>
select(filtrovanaData, name, year, wind)
# A tibble: 3 × 3
  name     year  wind
  <chr>   <dbl> <int>
1 Allison  1995    65
2 Allison  1995    65
3 Allison  1995    65

Příprava na další hodinu

Stáhněte si data, které budou přiloženy u lekce ve výukových materiálech. Nezapomeňte si je uložit do dedikované složky, žádné “najdu to ve stažených souborech”!

V příští lekci budeme pracovat s nahráváním dat a s projekty, proto je opravdu potřeba v tom mít pořádek.

Domácí úkol

  1. Vyber z následujícího vektoru každou pátou hodnotu

    seq(15.2, 45.7, 0.56)
     [1] 15.20 15.76 16.32 16.88 17.44 18.00 18.56 19.12 19.68 20.24 20.80 21.36
    [13] 21.92 22.48 23.04 23.60 24.16 24.72 25.28 25.84 26.40 26.96 27.52 28.08
    [25] 28.64 29.20 29.76 30.32 30.88 31.44 32.00 32.56 33.12 33.68 34.24 34.80
    [37] 35.36 35.92 36.48 37.04 37.60 38.16 38.72 39.28 39.84 40.40 40.96 41.52
    [49] 42.08 42.64 43.20 43.76 44.32 44.88 45.44
  2. Z datasetu (co je nahraný v R) jménem airquality, který obsahuje informace o měření kvality vzduchu v NYC, vyber hodnoty ze sloupce Temp z prvního týdne v květnu.

  3. K datasetu airquality přidejte nový sloupec s názvem Weather který bude obsahovat informaci (text hot), zda hodnoty ve sloupci Temp jsou vyšší než 70. Pokud není vyšší jako 70, bude obsahovat text cold.

Bonus: Pokuste se zjistit, jak si v nápovědě můžete najít seznam nahraných datasetů v R (iris, cars, dplyr::starwars a jiné)

Skript s výpočtem zašlete nejpozději do pátku před příští hodinou na lucie.hoskova@ruk.cuni.cz