Na motivy Hadley Wickham: Tidy data, Journal of Statistical Software, August 2014, Volume 59, Issue 10.
K této kapitole jsou zpracovány velice hezké „taháky“: http://www.rstudio.com/resources/cheatsheets/ (Data tidying with tidyr a Data transformation with dplyr). Jsou též dostupné přímo z RStudia z menu Help, Cheatsheets.
Všechny potřebné knihovny (dplyr, tidyr a readr) lze instalovat v rámci jednoho zastřešujícího balíčku tidyverse:
install.packages("tidyverse")
Před použitím knihoven je potřeba je nejdříve zavést příkazem (nutné vždy po startu R)
library(tidyverse)
Případně je možné obdobným způsobem instalovat jednotlivé knihovny…
Tidy Data je obecný koncept nezávislý na použitých programech.
Raw Data → Processing Script → Tidy data + Codebook → Data Analysis → Data Communication.
Raw Data: surová data, zaznamenaná v jakémkoliv prvotním (často neuspořádaném) formátu (klidně i jen poznámky na papíře).
Reprodukovatelnost: celý řetězec zpracování jednoznačně popsán skripty – na první pohled je jasný postup a lze ho jednoduše zopakovat. V případě ručních mezikroků detailně zaznamenat (verze programu, nastavení, jak co pojmenovat a jak uložit).
Codebook: informace o proměnných, jejich jednotkách a možných hodnotách. Slouží k tomu, aby se v datech vyznal a mohl s nimi pracovat i ten, kdo nebyl u jejich pořízení.
Tidy data
Poznámka k bodu 3: pokud máme např. tabulku s průběžnými body studentů během jejich studia, jedná se o jednu záležitost. Osobní informace o jednotlivých studentech (datum narození, adresa, telefon) uložíme do samostatné tabulky.
V případě více tabulek je nutný sloupec, dle kterého je lze propojit – ID pozorování – identifikační číslo, řetězec apod.
Čitelné pojmenování sloupců – raději AgeAtDiagnosis než AgeDx.
Uložení dat: co tabulka, to jeden soubor (záložkám v Excelu se vyhýbat). A rozhodně neukládat do jedné záložky více tabulek! Zbytečně si tím v extrémní míře znesnadňujeme následné automatické zpracování.
Messy data: vše ostatní.
Pokud jsou data v tidy formátu, můžeme využívat efektivních knihoven pro jejich další zpracování, například dplyr pro souhrnné statistiky a manipulace podle různých kritérií (viz dále v této kapitole) nebo ggplot2 pro efektivní tvorbu pokročilých grafů (viz kapitola Grammar of Graphics (ggplot2)).
Nyní se podívejme na data v nevhodném formátu a jak je převést na tidy data.
Tabulka obsahuje průměrnou hodnotu základní frekvence kmitání hlasivek (F0) u 3 žen a 3 mužů při 2 různých úkolech. Čím jsou porušena pravidla tidy data?
data <- read.table(header = TRUE, text = '
task male female
1 119 203
1 143 219
1 94 245
2 114 144
2 127 259
2 95 244
')
„Hlavičky některých sloupců jsou hodnoty, nikoliv jména proměnných.“
Hlavičky sloupců male a female ve skutečnosti nejsou 2 různé proměnné, ale jen 2 hodnoty téže proměnné (sex). Že to skutečně není vhodný formát tabulky, by bylo ještě zřejmější, pokud by se výzkumu zůčastnilo např. 5 žen a 3 muži.
Máme tedy 3 proměnné: task, sex a F0_mean. Opravu (sloučení sloupců) provedem pomocí funkce pivot_longer. Význam jejích parametrů je následující.
dataTidy <- pivot_longer(data, cols = c(male, female), names_to = "sex", values_to = "F0_mean")
Tímto zápisem říkáme: vezmi tabulku data, slučovat se budou sloupce male a female, z názvů slučovaných sloupců male a female se udělají hodnoty nového sloupce sex a čísla z těchto sloupců se převedou do nového sloupce s názvem F0_mean.
dataTidy
## # A tibble: 12 × 3
## task sex F0_mean
## <int> <chr> <int>
## 1 1 male 119
## 2 1 female 203
## 3 1 male 143
## 4 1 female 219
## 5 1 male 94
## 6 1 female 245
## 7 2 male 114
## 8 2 female 144
## 9 2 male 127
## 10 2 female 259
## 11 2 male 95
## 12 2 female 244
A máme krásný tidy data formát. Můžeme pak např. jednoduše pomocí grafické knihovny ggplot2 říct, ať zobrazí frekvence u jednotlivých úloh (task) a rozdělí se do skupin podle hodnot proměnné sex. Ale o tom až v další kapitole…
Poznámka: pro výběr slučovaných sloupců lze využít i zápisu se
symbolem -
značícím „vše kromě“, tedy sloučit všechny
sloupce kromě sloupce task:
dataTidy <- pivot_longer(data, cols = -task, names_to = "sex", values_to = "F0_mean")
Opět máme data z předchozího příkladu, ale v jiném tvaru. Čísla úkolů jsou součástí názvů sloupečků (_1 a _2). Čím jsou porušena pravidla tidy data?
data2 <- read.table(header = TRUE, text = '
male_1 male_2 female_1 female_2
119 114 203 144
143 127 219 259
94 95 245 244
')
Opět „hlavičky některých sloupců jsou hodnoty, nikoliv jména proměnných“, ale k tomu ještě „více proměnných v rámci jednoho sloupce“ (sex a task).
data2Tidy <- pivot_longer(data2, cols = everything(), names_to = "sex_task", values_to = "F0_mean") %>%
separate(sex_task, c("sex", "task"), sep = "_")
První funkci pivot_longer jsme již poznali (parametr cols nyní říká, ať se sloučí všechny sloupce), vytváříme dočasný sloupec se dvěma proměnnými sex_task (zkuste si spustit samostatně jen tuto operaci a podívejte se na výsledek).
## # A tibble: 12 × 2
## sex_task F0_mean
## <chr> <int>
## 1 male_1 119
## 2 male_2 114
## 3 female_1 203
## 4 female_2 144
## 5 male_1 143
## 6 male_2 127
## 7 female_1 219
## 8 female_2 259
## 9 male_1 94
## 10 male_2 95
## 11 female_1 245
## 12 female_2 244
Operátor %>%
se nazývá pipeline (potrubí, spojení) a
posílá výsledek z jedné funkce do druhé, takže není potřeba ukládat
mezivýsledky do proměnných. Pokud je tento operátor použit, následující
funkci nezadáváme 1. parametr (název proměnné s daty), protože data jsou
jí právě přeposlána tímto operátorem.
Funkce separate rozdělí řetězec na více částí podle zvoleného oddělovače (sep) a výsledek uloží do nových sloupců, jejichž název jsme zvolili sex a task.
data2Tidy
## # A tibble: 12 × 3
## sex task F0_mean
## <chr> <chr> <int>
## 1 male 1 119
## 2 male 2 114
## 3 female 1 203
## 4 female 2 144
## 5 male 1 143
## 6 male 2 127
## 7 female 1 219
## 8 female 2 259
## 9 male 1 94
## 10 male 2 95
## 11 female 1 245
## 12 female 2 244
Tabulka obsahuje trvání (duration) a průměrnou F0 u pěti různých úkolů. Ne všichni ale absolvovali všechny úkoly, proto tu máme spoustu chybějících hodnot NA (not available). Čím tabulka porušuje pravidla tidy data?
data3 <- read.table(header = TRUE, text = '
name parameter task1 task2 task3 task4 task5
Eva duration 4.8 NA 12.3 NA NA
Eva F0_mean 230 NA 222 NA NA
Jiří duration NA 7.0 NA 5.9 NA
Jiří F0_mean NA 110 NA 113 NA
Zbyněk duration NA 6.7 NA NA 15.1
Zbyněk F0_mean NA 127 NA NA 118
Monika duration NA NA 10.9 6.2 NA
Monika F0_mean NA NA 240 235 NA
Patrik duration 5.1 NA NA NA 16.3
Patrik F0_mean 98 NA NA NA 95
')
„Proměnné uloženy jak v řádcích, tak ve sloupcích.“
Name je o.k., ale task1 až task5 jsou jen hodnoty jedné proměnné task (5 různých úkolů), duration a F0_mean jsou dvě proměnné související s konkrétním jedním pokusem, tudíž by měly tvořit 2 sloupce vždy pro stejný řádek.
data3_krok1 <- pivot_longer(data3, cols = task1:task5, names_to = "task", values_to = "value",
values_drop_na = TRUE)
V prvním kroku vezmeme tabulku data3, všechny názvy sloupců v rozsahu task1 až task5 budou hodnoty nové proměnné task a příslušné hodnoty ze sloupců uložíme do nové proměnné value. Všechny hodnoty NA (not available) zahodíme.
## # A tibble: 20 × 4
## name parameter task value
## <chr> <chr> <chr> <dbl>
## 1 Eva duration task1 4.8
## 2 Eva duration task3 12.3
## 3 Eva F0_mean task1 230
## 4 Eva F0_mean task3 222
## 5 Jiří duration task2 7
## 6 Jiří duration task4 5.9
## 7 Jiří F0_mean task2 110
## 8 Jiří F0_mean task4 113
## 9 Zbyněk duration task2 6.7
## 10 Zbyněk duration task5 15.1
## 11 Zbyněk F0_mean task2 127
## 12 Zbyněk F0_mean task5 118
## 13 Monika duration task3 10.9
## 14 Monika duration task4 6.2
## 15 Monika F0_mean task3 240
## 16 Monika F0_mean task4 235
## 17 Patrik duration task1 5.1
## 18 Patrik duration task5 16.3
## 19 Patrik F0_mean task1 98
## 20 Patrik F0_mean task5 95
data3_krok2 <- mutate(data3_krok1, task = parse_number(task))
Z hodnot proměnné task (které jsou task1, task2
atd.) extrahujeme jen číslo (funkcí parse_number
z balíčku
readr
), to nám stačí.
## # A tibble: 20 × 4
## name parameter task value
## <chr> <chr> <dbl> <dbl>
## 1 Eva duration 1 4.8
## 2 Eva duration 3 12.3
## 3 Eva F0_mean 1 230
## 4 Eva F0_mean 3 222
## 5 Jiří duration 2 7
## 6 Jiří duration 4 5.9
## 7 Jiří F0_mean 2 110
## 8 Jiří F0_mean 4 113
## 9 Zbyněk duration 2 6.7
## 10 Zbyněk duration 5 15.1
## 11 Zbyněk F0_mean 2 127
## 12 Zbyněk F0_mean 5 118
## 13 Monika duration 3 10.9
## 14 Monika duration 4 6.2
## 15 Monika F0_mean 3 240
## 16 Monika F0_mean 4 235
## 17 Patrik duration 1 5.1
## 18 Patrik duration 5 16.3
## 19 Patrik F0_mean 1 98
## 20 Patrik F0_mean 5 95
data3Tidy <- pivot_wider(data3_krok2, names_from = parameter, values_from = value)
Z hodnot proměnné parameter vytvoříme nové proměnné (nové sloupce), jejichž hodnoty naplníme z proměné value (v nové tabulce tím tedy proměnné parameter a value zaniknou, o konkrétní hodnoty samozřejme nepřijdeme, jen budou přemístěny do jiného formátu).
data3Tidy
## # A tibble: 10 × 4
## name task duration F0_mean
## <chr> <dbl> <dbl> <dbl>
## 1 Eva 1 4.8 230
## 2 Eva 3 12.3 222
## 3 Jiří 2 7 110
## 4 Jiří 4 5.9 113
## 5 Zbyněk 2 6.7 127
## 6 Zbyněk 5 15.1 118
## 7 Monika 3 10.9 240
## 8 Monika 4 6.2 235
## 9 Patrik 1 5.1 98
## 10 Patrik 5 16.3 95
Celý postup by samozřejmě bylo možné zapsat najednou pomocí operátoru
pipeline %>%
. Zkuste si to.
Čím jsou porušena pravidla tidy data?
data4 <- read.table(header = TRUE, text = '
id name sex task duration F0_mean
168 Eva F 1 4.8 230
168 Eva F 3 12.3 222
588 Jiří M 2 7.0 110
588 Jiří M 4 5.9 113
710 Monika F 3 10.9 240
710 Monika F 4 6.2 235
731 Patrik M 1 5.1 98
731 Patrik M 5 16.3 95
908 Zbyněk M 2 6.7 127
908 Zbyněk M 5 15.1 118
')
„Více pozorovaných záležitostí uložených ve stejné tabulce.“
Osobní informace o lidech (id, name, sex) – vše je 2x, to je jasná známka redundance (a ještě je tu riziko překlepu).
Data je vhodné rozdělit do 2 tabulek: idInfo a results. Obě tabulky budou propojeny přes id číslo.
idInfo <- data4 %>% select(id, name, sex) %>% unique
Z tabulky jsme funkcí select vybrali první 3 sloupce. Funkcí unique jsme zanechali jen unikátní řádky. Pokud se řádky opakují, ve výsledku budou zahrnuty pouze jednou.
idInfo
## id name sex
## 1 168 Eva F
## 3 588 Jiří M
## 5 710 Monika F
## 7 731 Patrik M
## 9 908 Zbyněk M
results <- data4 %>% select(id, task, duration, F0_mean)
A opět vybíráme jen některé sloupce.
results
## id task duration F0_mean
## 1 168 1 4.8 230
## 2 168 3 12.3 222
## 3 588 2 7.0 110
## 4 588 4 5.9 113
## 5 710 3 10.9 240
## 6 710 4 6.2 235
## 7 731 1 5.1 98
## 8 731 5 16.3 95
## 9 908 2 6.7 127
## 10 908 5 15.1 118
Mít takto oddělené záznamy je praktické. V případě potřeby je pak možné informace kdykoliv spojit.
right_join(idInfo, results, by = "id")
## id name sex task duration F0_mean
## 1 168 Eva F 1 4.8 230
## 2 168 Eva F 3 12.3 222
## 3 588 Jiří M 2 7.0 110
## 4 588 Jiří M 4 5.9 113
## 5 710 Monika F 3 10.9 240
## 6 710 Monika F 4 6.2 235
## 7 731 Patrik M 1 5.1 98
## 8 731 Patrik M 5 16.3 95
## 9 908 Zbyněk M 2 6.7 127
## 10 908 Zbyněk M 5 15.1 118
Pro další způsoby spojování tabulek viz tahák dostupný přímo z RStudia z menu Help, Cheatsheets, Data Manipulation v dplyr, tidyr. Druhá strana, sekce Combine Data Sets.
Čím jsou zde porušena pravidla tidy data?
male <- read.table(header = TRUE, text = '
name task duration F0_mean
Jiří 2 7 110
Jiří 4 5.9 113
Patrik 1 5.1 98
Patrik 5 16.3 95
Zbyněk 2 6.7 127
Zbyněk 5 15.1 118
')
female <- read.table(header = TRUE, text = '
name task duration F0_mean
Eva 1 4.8 230
Eva 3 12.3 222
Monika 3 10.9 240
Monika 4 6.2 235
')
„Jedna pozorovaná záležitost uložena ve více tabulkách.“
Pokud se jedná o stejný experiment, obě tabulky má smysl sloučit a z male a female vytvořit jednu proměnnou sex.
male <- male %>% mutate(sex = "M")
female <- female %>% mutate(sex = "F")
Tímto jsme do tabulek přidali novou proměnnou sex s příslušnou hodnotou ve všech řádcích.
data5Tidy <- bind_rows(male, female)
A obě tabulky spojíme pod sebe.
data5Tidy
## name task duration F0_mean sex
## 1 Jiří 2 7.0 110 M
## 2 Jiří 4 5.9 113 M
## 3 Patrik 1 5.1 98 M
## 4 Patrik 5 16.3 95 M
## 5 Zbyněk 2 6.7 127 M
## 6 Zbyněk 5 15.1 118 M
## 7 Eva 1 4.8 230 F
## 8 Eva 3 12.3 222 F
## 9 Monika 3 10.9 240 F
## 10 Monika 4 6.2 235 F
Občas se při zpracování dat dostaneme do situace, kdy je potřeba tidy tabulku záměrně předělat do „messy“ tvaru. V následujícím příkladu jsme nahráli 3 osoby, každá přečetla jednu větu ve dvou stylech fonace, a sice normální (modal) a třepené (creaky). Vše bylo čteno dvakrát (sloupec order). Vypočteno bylo trvání a průměrná hodnota F0.
data <- read.table(header = TRUE, text = '
speaker phonation order duration F0_mean
1 modal 1 5.7 127
1 modal 2 5.3 135
1 creaky 1 8.5 110
1 creaky 2 7.4 105
2 modal 1 6.3 243
2 creaky 1 9.2 145
2 modal 2 5.8 219
2 creaky 2 9.3 162
3 modal 1 5.1 140
3 creaky 1 6.0 93
3 creaky 2 5.8 95
')
Rádi bychom vytvořili sloupce s jednotlivými vypočtenými parametry doplněné o index 1 nebo 2 odpovídající hodnotě ve sloupci order, aby pak bylo možné jednoduše vypočítat rozdíl mezi hodnotami prvního a druhého čtení té samé položky tou samou fonací.
messy <- pivot_wider(data, id_cols = c(speaker, phonation), # sloupce sloužící k identifikaci položky
names_from = "order", # sloupec "order" udává pořadí, podle něj se očíslují nové sloupce
values_from = duration:F0_mean, # výčet sloupců s naměřenými hodnotami
names_glue = "{.value}.{order}") # jak slepit nové názvy - zde opět sloupec "order"
## # A tibble: 6 × 6
## speaker phonation duration.1 duration.2 F0_mean.1 F0_mean.2
## <int> <chr> <dbl> <dbl> <int> <int>
## 1 1 modal 5.7 5.3 127 135
## 2 1 creaky 8.5 7.4 110 105
## 3 2 modal 6.3 5.8 243 219
## 4 2 creaky 9.2 9.3 145 162
## 5 3 modal 5.1 NA 140 NA
## 6 3 creaky 6 5.8 93 95
Nyní můžeme vypočítat rozdíly parametrů mezi 1. a 2. čtením. Všimněme si, že bylo správně rozpoznáno, že u třetí osoby chybí druhé čtení v modální fonaci. Ani prohozené pořadí řádků u druhé osoby (vůči logice zbylých dvou osob) převod tabulky nijak nerozhodilo. Kdybychom tyto úpravy dělali ručně, riziko chyby by bylo vysoké.
tab <- messy %>% mutate(deltaDuration = duration.2 - duration.1, deltaF0_mean = F0_mean.2 - F0_mean.1) %>%
select(speaker, phonation, deltaDuration, deltaF0_mean)
## # A tibble: 6 × 4
## speaker phonation deltaDuration deltaF0_mean
## <int> <chr> <dbl> <int>
## 1 1 modal -0.400 8
## 2 1 creaky -1.1 -5
## 3 2 modal -0.5 -24
## 4 2 creaky 0.100 17
## 5 3 modal NA NA
## 6 3 creaky -0.200 2
Rozdíly jsou bezchybně určeny a správně chybí modální fonace třetí osoby, jelikož v datech není druhé čtení.
Kontingenční tabulka, neboli tabulka se dvěma vstupy a souhrnnými počty také z principu odporuje formátu tidy data. Přesto je velmi užitečná právě pro zobrazení souhrnných počtů nebo pro statistické testy porovnávající četnosti.
Primární formát uchování dat by měl být tidy data (např. co řádek tabulky, to jeden náhodný výběr ze základního souboru) a převod na kontingenční tabulku pak již snadno provedeme funkcí table(), jak je uvedeno na příkladech v kapitole 15. Testy četností.
Nyní přichází ta zábavnější část. Předpokládejme, že máme tabulku ve správném formátu tidy data. Pak je radost s ní pracovat. Nejlepší je samozřejmě data hned od začátku ukládat do formátu tidy data, ušetříme si tím starosti. Pakliže ale tento formát nesplňují, musíme je na tidy data nejdříve převést, o čemž byla horní část této stránky.
Funkce v dplyr jsou určeny pro jednodušší a efektivnější spravování dat. Zápis těchto operací je oproti dřívějším knihovnám velice zjednodušen a implementace je vskutku bleskurychlá. Některé funkce jsme již poznali výše.
Knihovna dplyr implementuje „gramatiku“ pro manipulaci s daty (konkrétně slovesa).
Dále můžeme používat operátor %>%
(pipeline), který
jsme již poznali výše.
Budeme pracovat s interním dataframe mtcars, seznamte se s ním proto pomocí funkcí View(mtcars) a nápovědy ?mtcars.
Všimněme si, že názvy automobilů jsou uloženy jen jako názvy řádků tabulky. Uděláme z nich „oficiální proměnnou“, tedy nový sloupec.
mtcars$car <- rownames(mtcars)
Seřadíme tabulku podle sloupce car.
mtcars <- mtcars %>% arrange(car)
mtcars
## mpg cyl disp hp drat wt qsec vs am gear carb
## AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
## Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
## Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
## Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
## Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
## Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
## Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
## car
## AMC Javelin AMC Javelin
## Cadillac Fleetwood Cadillac Fleetwood
## Camaro Z28 Camaro Z28
## Datsun 710 Datsun 710
## Dodge Challenger Dodge Challenger
## Duster 360 Duster 360
## Ferrari Dino Ferrari Dino
## Fiat 128 Fiat 128
## Fiat X1-9 Fiat X1-9
## Ford Pantera L Ford Pantera L
## Honda Civic Honda Civic
## Hornet 4 Drive Hornet 4 Drive
## Hornet Sportabout Hornet Sportabout
## Chrysler Imperial Chrysler Imperial
## Lincoln Continental Lincoln Continental
## Lotus Europa Lotus Europa
## Maserati Bora Maserati Bora
## Mazda RX4 Mazda RX4
## Mazda RX4 Wag Mazda RX4 Wag
## Merc 230 Merc 230
## Merc 240D Merc 240D
## Merc 280 Merc 280
## Merc 280C Merc 280C
## Merc 450SE Merc 450SE
## Merc 450SL Merc 450SL
## Merc 450SLC Merc 450SLC
## Pontiac Firebird Pontiac Firebird
## Porsche 914-2 Porsche 914-2
## Toyota Corolla Toyota Corolla
## Toyota Corona Toyota Corona
## Valiant Valiant
## Volvo 142E Volvo 142E
Používá to defaultní Locale našeho systému, což bývá např. Czech. Takže Chrysler je až a Hornet.
Sys.getlocale(category = "LC_ALL") # zjisti nastavení Locale
## [1] "LC_COLLATE=Czech_Czechia.utf8;LC_CTYPE=Czech_Czechia.utf8;LC_MONETARY=Czech_Czechia.utf8;LC_NUMERIC=C;LC_TIME=Czech_Czechia.utf8"
Sys.setlocale(category = "LC_COLLATE", locale = "English") # nastav Anglické Locale pro řazení
## [1] "English_United States.1252"
mtcars <- mtcars %>% arrange(car)
mtcars
## mpg cyl disp hp drat wt qsec vs am gear carb
## AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
## Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
## Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
## Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
## Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
## Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
## Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
## car
## AMC Javelin AMC Javelin
## Cadillac Fleetwood Cadillac Fleetwood
## Camaro Z28 Camaro Z28
## Chrysler Imperial Chrysler Imperial
## Datsun 710 Datsun 710
## Dodge Challenger Dodge Challenger
## Duster 360 Duster 360
## Ferrari Dino Ferrari Dino
## Fiat 128 Fiat 128
## Fiat X1-9 Fiat X1-9
## Ford Pantera L Ford Pantera L
## Honda Civic Honda Civic
## Hornet 4 Drive Hornet 4 Drive
## Hornet Sportabout Hornet Sportabout
## Lincoln Continental Lincoln Continental
## Lotus Europa Lotus Europa
## Maserati Bora Maserati Bora
## Mazda RX4 Mazda RX4
## Mazda RX4 Wag Mazda RX4 Wag
## Merc 230 Merc 230
## Merc 240D Merc 240D
## Merc 280 Merc 280
## Merc 280C Merc 280C
## Merc 450SE Merc 450SE
## Merc 450SL Merc 450SL
## Merc 450SLC Merc 450SLC
## Pontiac Firebird Pontiac Firebird
## Porsche 914-2 Porsche 914-2
## Toyota Corolla Toyota Corolla
## Toyota Corona Toyota Corona
## Valiant Valiant
## Volvo 142E Volvo 142E
Nyní je Chrysler před Datsun.
Seřadíme ji podle cyl (sestupně) a v případě více shodných hodnot budeme řadit ještě podle gear (normálně vzestupně).
mtcars <- mtcars %>% arrange(desc(cyl), gear)
mtcars
## mpg cyl disp hp drat wt qsec vs am gear carb
## AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
## Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
## Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
## Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
## Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
## Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
## Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
## Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
## Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
## Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## car
## AMC Javelin AMC Javelin
## Cadillac Fleetwood Cadillac Fleetwood
## Camaro Z28 Camaro Z28
## Chrysler Imperial Chrysler Imperial
## Dodge Challenger Dodge Challenger
## Duster 360 Duster 360
## Hornet Sportabout Hornet Sportabout
## Lincoln Continental Lincoln Continental
## Merc 450SE Merc 450SE
## Merc 450SL Merc 450SL
## Merc 450SLC Merc 450SLC
## Pontiac Firebird Pontiac Firebird
## Ford Pantera L Ford Pantera L
## Maserati Bora Maserati Bora
## Hornet 4 Drive Hornet 4 Drive
## Valiant Valiant
## Mazda RX4 Mazda RX4
## Mazda RX4 Wag Mazda RX4 Wag
## Merc 280 Merc 280
## Merc 280C Merc 280C
## Ferrari Dino Ferrari Dino
## Toyota Corona Toyota Corona
## Datsun 710 Datsun 710
## Fiat 128 Fiat 128
## Fiat X1-9 Fiat X1-9
## Honda Civic Honda Civic
## Merc 230 Merc 230
## Merc 240D Merc 240D
## Toyota Corolla Toyota Corolla
## Volvo 142E Volvo 142E
## Lotus Europa Lotus Europa
## Porsche 914-2 Porsche 914-2
Přejmenujeme sloupec am na razeni.
mtcars <- mtcars %>% rename(razeni = am)
head(mtcars)
## mpg cyl disp hp drat wt qsec vs razeni gear carb
## AMC Javelin 15.2 8 304 150 3.15 3.435 17.30 0 0 3 2
## Cadillac Fleetwood 10.4 8 472 205 2.93 5.250 17.98 0 0 3 4
## Camaro Z28 13.3 8 350 245 3.73 3.840 15.41 0 0 3 4
## Chrysler Imperial 14.7 8 440 230 3.23 5.345 17.42 0 0 3 4
## Dodge Challenger 15.5 8 318 150 2.76 3.520 16.87 0 0 3 2
## Duster 360 14.3 8 360 245 3.21 3.570 15.84 0 0 3 4
## car
## AMC Javelin AMC Javelin
## Cadillac Fleetwood Cadillac Fleetwood
## Camaro Z28 Camaro Z28
## Chrysler Imperial Chrysler Imperial
## Dodge Challenger Dodge Challenger
## Duster 360 Duster 360
Vybereme jen sloupce car a mpg (dojezd v mílích na gallon).
prehled <- mtcars %>% select(car, mpg)
head(prehled)
## car mpg
## AMC Javelin AMC Javelin 15.2
## Cadillac Fleetwood Cadillac Fleetwood 10.4
## Camaro Z28 Camaro Z28 13.3
## Chrysler Imperial Chrysler Imperial 14.7
## Dodge Challenger Dodge Challenger 15.5
## Duster 360 Duster 360 14.3
Vybereme jen řádky, kde vs = 0 a carb >= 4, výsledek seřadíme podle názvu.
vyber <- mtcars %>% filter(vs == 0, carb >= 4) %>% arrange(car)
vyber
## mpg cyl disp hp drat wt qsec vs razeni gear carb
## Cadillac Fleetwood 10.4 8 472 205 2.93 5.250 17.98 0 0 3 4
## Camaro Z28 13.3 8 350 245 3.73 3.840 15.41 0 0 3 4
## Chrysler Imperial 14.7 8 440 230 3.23 5.345 17.42 0 0 3 4
## Duster 360 14.3 8 360 245 3.21 3.570 15.84 0 0 3 4
## Ferrari Dino 19.7 6 145 175 3.62 2.770 15.50 0 1 5 6
## Ford Pantera L 15.8 8 351 264 4.22 3.170 14.50 0 1 5 4
## Lincoln Continental 10.4 8 460 215 3.00 5.424 17.82 0 0 3 4
## Maserati Bora 15.0 8 301 335 3.54 3.570 14.60 0 1 5 8
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## car
## Cadillac Fleetwood Cadillac Fleetwood
## Camaro Z28 Camaro Z28
## Chrysler Imperial Chrysler Imperial
## Duster 360 Duster 360
## Ferrari Dino Ferrari Dino
## Ford Pantera L Ford Pantera L
## Lincoln Continental Lincoln Continental
## Maserati Bora Maserati Bora
## Mazda RX4 Mazda RX4
## Mazda RX4 Wag Mazda RX4 Wag
Zavedeme novou proměnnou (sloupec) udávající, zda mají auta nadprůměrně nízkou spotřebu.
mtcars <- mtcars %>% mutate(usporne = (mpg > mean(mpg)))
mtcars
## mpg cyl disp hp drat wt qsec vs razeni gear carb
## AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
## Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
## Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
## Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
## Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
## Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
## Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
## Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
## Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
## Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## car usporne
## AMC Javelin AMC Javelin FALSE
## Cadillac Fleetwood Cadillac Fleetwood FALSE
## Camaro Z28 Camaro Z28 FALSE
## Chrysler Imperial Chrysler Imperial FALSE
## Dodge Challenger Dodge Challenger FALSE
## Duster 360 Duster 360 FALSE
## Hornet Sportabout Hornet Sportabout FALSE
## Lincoln Continental Lincoln Continental FALSE
## Merc 450SE Merc 450SE FALSE
## Merc 450SL Merc 450SL FALSE
## Merc 450SLC Merc 450SLC FALSE
## Pontiac Firebird Pontiac Firebird FALSE
## Ford Pantera L Ford Pantera L FALSE
## Maserati Bora Maserati Bora FALSE
## Hornet 4 Drive Hornet 4 Drive TRUE
## Valiant Valiant FALSE
## Mazda RX4 Mazda RX4 TRUE
## Mazda RX4 Wag Mazda RX4 Wag TRUE
## Merc 280 Merc 280 FALSE
## Merc 280C Merc 280C FALSE
## Ferrari Dino Ferrari Dino FALSE
## Toyota Corona Toyota Corona TRUE
## Datsun 710 Datsun 710 TRUE
## Fiat 128 Fiat 128 TRUE
## Fiat X1-9 Fiat X1-9 TRUE
## Honda Civic Honda Civic TRUE
## Merc 230 Merc 230 TRUE
## Merc 240D Merc 240D TRUE
## Toyota Corolla Toyota Corolla TRUE
## Volvo 142E Volvo 142E TRUE
## Lotus Europa Lotus Europa TRUE
## Porsche 914-2 Porsche 914-2 TRUE
A nyní by mě zajímalo, kolik průměrně váží auta s nízkou spotřebou a kolik ta s vysokou.
mtcars %>% group_by(usporne) %>% summarize(wtPrumer = mean(wt))
## # A tibble: 2 × 2
## usporne wtPrumer
## <lgl> <dbl>
## 1 FALSE 3.84
## 2 TRUE 2.42
Tak to vypadá, že úsporná auta jsou spíše ta lehčí (opět připomeňme, že souvislost neznamená nutně kauzalitu).
Zvládli bychom vypočítat i 95% konfidenční intervaly tohoto odhadu? V jednom sloupci může být vždy jen jedno číslo, takže interval bude ve dvou sloupcích (spodní a horní hodnota).
mtcars %>% group_by(usporne) %>% summarize(wtPrumer = mean(wt),
confInt1 = t.test(wt)$conf.int[1], confInt2 = t.test(wt)$conf.int[2])
## # A tibble: 2 × 4
## usporne wtPrumer confInt1 confInt2
## <lgl> <dbl> <dbl> <dbl>
## 1 FALSE 3.84 3.47 4.21
## 2 TRUE 2.42 2.09 2.75
A pojďme vymyslet složitější skupiny. Rozdělíme data podle převodovky (razeni), válců (cyl) a počtu karburátorů (carb). V těchto skupinách vypočteme průměr a směrodatnou odchylku z mpg a wt. Výsledky seřadíme od největší průměrné mpg po nejmenší.
Vidíme, že některé skupiny byly asi zastoupeny jen jednou položkou, a proto nebylo možné vypočítat směrodatnou odchylku.
mtcars %>% group_by(razeni, cyl, carb) %>%
summarize(mpgPrumer = mean(mpg), mpgSD = sd(mpg), wtPrumer = mean(wt), wtSD = sd(wt)) %>%
arrange(desc(mpgPrumer))
## `summarise()` has grouped output by 'razeni', 'cyl'. You can override using the
## `.groups` argument.
## # A tibble: 13 × 7
## # Groups: razeni, cyl [6]
## razeni cyl carb mpgPrumer mpgSD wtPrumer wtSD
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 4 1 29.1 5.06 2.07 0.226
## 2 1 4 2 27.0 4.3 2.01 0.581
## 3 0 4 2 23.6 1.13 3.17 0.0283
## 4 0 4 1 21.5 NA 2.46 NA
## 5 1 6 4 21 0 2.75 0.180
## 6 0 6 1 19.8 2.33 3.34 0.173
## 7 1 6 6 19.7 NA 2.77 NA
## 8 0 6 4 18.5 0.990 3.44 0
## 9 0 8 2 17.2 2.09 3.56 0.194
## 10 0 8 3 16.3 1.05 3.86 0.184
## 11 1 8 4 15.8 NA 3.17 NA
## 12 1 8 8 15 NA 3.57 NA
## 13 0 8 4 12.6 2.09 4.69 0.903
A nyní chceme udělat nějaké výpočty pro každou skupinu z group_by() samostatně, ale výsledkem nemá být jen souhrnná statistika, ale normálně celá tabulka. K tomu slouží funkce group_modify(). Příklad: rozdělíme do skupin podle počtu válců (cyl), v každé skupině samostatně vypočteme průměrné mpg a vytvoříme nový sloupeček rozdilMPG vypočtený jako mpg mínus průměrMPG.
odectiPrumerMPG <- function(tabulka) { # vstupem funkce je data.frame = vyrez radku z puvodni tabulky
# odpovidajici konkretni skupine podle provedeneho group_by()
tabulka$rozdilMPG <- tabulka$mpg - mean(tabulka$mpg) # ...napr. vypocteme novy sloupecek...
tabulka <- tabulka %>% select(-c(disp:carb)) # ...a treba odstranime nektere jine sloupce...
return(tabulka) # vystupem funkce musi byt take data.frame
}
tabulkaRozdilu <- mtcars %>% group_by(cyl) %>% group_modify(.f = ~ odectiPrumerMPG(.x))
# .x je docasne jmeno data.frame vzdy jedne skupiny z group_by()
print(tabulkaRozdilu, n = 32)
## # A tibble: 32 × 5
## # Groups: cyl [3]
## cyl mpg car usporne rozdilMPG
## <dbl> <dbl> <chr> <lgl> <dbl>
## 1 4 21.5 Toyota Corona TRUE -5.16
## 2 4 22.8 Datsun 710 TRUE -3.86
## 3 4 32.4 Fiat 128 TRUE 5.74
## 4 4 27.3 Fiat X1-9 TRUE 0.636
## 5 4 30.4 Honda Civic TRUE 3.74
## 6 4 22.8 Merc 230 TRUE -3.86
## 7 4 24.4 Merc 240D TRUE -2.26
## 8 4 33.9 Toyota Corolla TRUE 7.24
## 9 4 21.4 Volvo 142E TRUE -5.26
## 10 4 30.4 Lotus Europa TRUE 3.74
## 11 4 26 Porsche 914-2 TRUE -0.664
## 12 6 21.4 Hornet 4 Drive TRUE 1.66
## 13 6 18.1 Valiant FALSE -1.64
## 14 6 21 Mazda RX4 TRUE 1.26
## 15 6 21 Mazda RX4 Wag TRUE 1.26
## 16 6 19.2 Merc 280 FALSE -0.543
## 17 6 17.8 Merc 280C FALSE -1.94
## 18 6 19.7 Ferrari Dino FALSE -0.0429
## 19 8 15.2 AMC Javelin FALSE 0.100
## 20 8 10.4 Cadillac Fleetwood FALSE -4.7
## 21 8 13.3 Camaro Z28 FALSE -1.80
## 22 8 14.7 Chrysler Imperial FALSE -0.400
## 23 8 15.5 Dodge Challenger FALSE 0.400
## 24 8 14.3 Duster 360 FALSE -0.800
## 25 8 18.7 Hornet Sportabout FALSE 3.6
## 26 8 10.4 Lincoln Continental FALSE -4.7
## 27 8 16.4 Merc 450SE FALSE 1.30
## 28 8 17.3 Merc 450SL FALSE 2.20
## 29 8 15.2 Merc 450SLC FALSE 0.100
## 30 8 19.2 Pontiac Firebird FALSE 4.1
## 31 8 15.8 Ford Pantera L FALSE 0.700
## 32 8 15 Maserati Bora FALSE -0.100
© 13. 5. 2015, 27. 10. 2020 Tomáš Bořil, borilt@gmail.com