Kromě balíčku tidyverse použijeme několik nových balíčků:
Rovněž využijeme několik custom funkcí ze souboru
r101_funs.R
. Pomocí příkazu source můžeme soubor načíst i
rovnou z internetu.
library(tidyverse)
library(haven)
library(dlookr)
library(skimr)
library(ggmosaic)
library(corrplot)
source("https://is.muni.cz/el/fss/podzim2022/PSYn5320/um/r101_funs.R")
Jako cvičná data použijeme dataset s údaji o prodeji videoher, který obsahuje tyto proměnné:
name
: název videohry.platform
: pro kterou herní platformu je hra
určena.year_of_release
: rok vydání.genre
: žánr (např. FPS, RPG apod.).publisher
: herní vydavatel, který hru vydal.na_sales
: tržby z prodeje hry v Severní america (v
milionech dolarů).eu_sales
: tržby z prodeje hry v Evropě (v milionech
dolarů).jp_sales
: tržby z prodeje hry v Japonsku (v milionech
dolarů).other_sales
: tržby z prodeje hry v ostatních částech
světa (v milionech dolarů).total_sales
: celkové tržby (v milionech dolarů).critic_score
: průměrné hodnocení profesionálních
recenzentů od 0 do 100.user_score
: průměrné hodnocení běžných hráčůuser_count
: počet hráčů, kteří si hru zakoupili (v
milionech).developer
: developer (herní vývojář/studio), který hru
vytvořil.rating
: rating pro hodnocení obsahu videoher.
post_2010
: zda byla hra vydáva po roce 2010.decade
: v které dekádě byla hra vydána (od 1980s po
2010s).platform_type
: typ herní platformy, např. Nintendo,
Playstation, PC atd.generation
: “generace” herní platformy.handheld
: jedná se o přenosnou herní platformu?<- read_rds("https://is.muni.cz/el/fss/podzim2022/PSYn5320/um/datasets/games_sales.rds")
df glimpse(df)
#> Rows: 16,719
#> Columns: 21
#> $ name <chr> "Wii Sports", "Super Mario Bros.", "Mario Kart Wii", "…
#> $ platform <chr> "Wii", "NES", "Wii", "Wii", "GB", "GB", "DS", "Wii", "…
#> $ year_of_release <dbl> 2006, 1985, 2008, 2009, 1996, 1989, 2006, 2006, 2009, …
#> $ genre <fct> Sports, Platform, Racing, Sports, Role-Playing, Puzzle…
#> $ publisher <chr> "Nintendo", "Nintendo", "Nintendo", "Nintendo", "Ninte…
#> $ na_sales <dbl> 41.36, 29.08, 15.68, 15.61, 11.27, 23.20, 11.28, 13.96…
#> $ eu_sales <dbl> 28.96, 3.58, 12.76, 10.93, 8.89, 2.26, 9.14, 9.18, 6.9…
#> $ jp_sales <dbl> 3.77, 6.81, 3.79, 3.28, 10.22, 4.22, 6.50, 2.93, 4.70,…
#> $ other_sales <dbl> 8.45, 0.77, 3.29, 2.95, 1.00, 0.58, 2.88, 2.84, 2.24, …
#> $ global_sales <dbl> 82.53, 40.24, 35.52, 32.77, 31.37, 30.26, 29.80, 28.92…
#> $ critic_score <dbl> 76, NA, 82, 80, NA, NA, 89, 58, 87, NA, NA, 91, NA, 80…
#> $ critic_count <dbl> 51, NA, 73, 73, NA, NA, 65, 41, 80, NA, NA, 64, NA, 63…
#> $ user_score <dbl> 8.0, NA, 8.3, 8.0, NA, NA, 8.5, 6.6, 8.4, NA, NA, 8.6,…
#> $ user_count <dbl> 322, NA, 709, 192, NA, NA, 431, 129, 594, NA, NA, 464,…
#> $ developer <chr> "Nintendo", NA, "Nintendo", "Nintendo", NA, NA, "Ninte…
#> $ rating <fct> E/10+, NA, E/10+, E/10+, NA, NA, E/10+, E/10+, E/10+, …
#> $ post_2010 <fct> No, No, No, No, No, No, No, No, No, No, No, No, No, No…
#> $ decade <fct> 2000s, 1980s, 2000s, 2000s, 1990s, 1980s, 2000s, 2000s…
#> $ platform_type <fct> Nintendo, Nintendo, Nintendo, Nintendo, Nintendo, Nint…
#> $ generation <fct> 7th, 3rd, 7th, 7th, 4th, 4th, 7th, 7th, 7th, 3rd, 7th,…
#> $ handheld <fct> No, No, No, No, Yes, Yes, Yes, No, No, No, Yes, Yes, Y…
Hlavní funkcí balíčku skimr je funkce skim()
, která
funguje s dataframy včetně tibbles a dodržuje i rozdělení do skupin
pomocí funkce group_by()
.
Podobně jako funkce summary()
poskytuje deskriptivní
statistiky všech proměnných a typ statistik závisí na typu proměnné,
protože by např. nemělo smysl počítat průměry pro kategorické proměnné,
ale jen pro numerické.
<- skim(df)
data_summary data_summary
#> ── Data Summary ────────────────────────
#> Values
#> Name df
#> Number of rows 16719
#> Number of columns 21
#> _______________________
#> Column type frequency:
#> factor 7
#> character 4
#> numeric 10
#> ________________________
#> Group variables None
#>
#> ── Variable type: factor ───────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate ordered n_unique
#> 1 genre 2 1.00 FALSE 12
#> 2 rating 6769 0.595 FALSE 5
#> 3 post_2010 0 1 FALSE 2
#> 4 decade 269 0.984 FALSE 4
#> 5 platform_type 0 1 FALSE 5
#> 6 generation 0 1 FALSE 8
#> 7 handheld 0 1 FALSE 2
#> top_counts
#> 1 Act: 3370, Spo: 2348, Mis: 1750, Rol: 1500
#> 2 E/1: 5411, T: 2961, M/A: 1564, EC/: 11
#> 3 No: 11169, Yes: 5550
#> 4 200: 9193, 201: 5281, 199: 1771, 198: 205
#> 5 Pla: 6723, Nin: 6271, XBo: 2333, PC: 974
#> 6 7th: 7274, 6th: 4415, 8th: 1739, 5th: 1699
#> 7 No: 10923, Yes: 5796
#>
#> ── Variable type: character ────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate min max empty n_unique whitespace
#> 1 name 2 1.00 1 132 0 11562 0
#> 2 platform 0 1 2 4 0 31 0
#> 3 publisher 54 0.997 3 38 0 580 0
#> 4 developer 6623 0.604 2 80 0 1696 0
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate mean sd p0 p25
#> 1 year_of_release 269 0.984 2006. 5.88 1980 2003
#> 2 na_sales 0 1 0.263 0.814 0 0
#> 3 eu_sales 0 1 0.145 0.503 0 0
#> 4 jp_sales 0 1 0.0776 0.309 0 0
#> 5 other_sales 0 1 0.0473 0.187 0 0
#> 6 global_sales 0 1 0.534 1.55 0.01 0.06
#> 7 critic_score 8582 0.487 69.0 13.9 13 60
#> 8 critic_count 8582 0.487 26.4 19.0 3 12
#> 9 user_score 9129 0.454 7.13 1.50 0 6.4
#> 10 user_count 9129 0.454 162. 561. 4 10
#> p50 p75 p100 hist
#> 1 2007 2010 2020 ▁▁▃▇▂
#> 2 0.08 0.24 41.4 ▇▁▁▁▁
#> 3 0.02 0.11 29.0 ▇▁▁▁▁
#> 4 0 0.04 10.2 ▇▁▁▁▁
#> 5 0.01 0.03 10.6 ▇▁▁▁▁
#> 6 0.17 0.47 82.5 ▇▁▁▁▁
#> 7 71 79 98 ▁▁▅▇▃
#> 8 21 36 113 ▇▃▂▁▁
#> 9 7.5 8.2 9.7 ▁▁▂▇▇
#> 10 24 81 10665 ▇▁▁▁▁
str(data_summary)
#> skim_df [21 × 20] (S3: skim_df/tbl_df/tbl/data.frame)
#> $ skim_type : chr [1:21] "factor" "factor" "factor" "factor" ...
#> $ skim_variable : chr [1:21] "genre" "rating" "post_2010" "decade" ...
#> $ n_missing : int [1:21] 2 6769 0 269 0 0 0 2 0 54 ...
#> $ complete_rate : num [1:21] 1 0.595 1 0.984 1 ...
#> $ factor.ordered : logi [1:21] FALSE FALSE FALSE FALSE FALSE FALSE ...
#> $ factor.n_unique : int [1:21] 12 5 2 4 5 8 2 NA NA NA ...
#> $ factor.top_counts : chr [1:21] "Act: 3370, Spo: 2348, Mis: 1750, Rol: 1500" "E/1: 5411, T: 2961, M/A: 1564, EC/: 11" "No: 11169, Yes: 5550" "200: 9193, 201: 5281, 199: 1771, 198: 205" ...
#> $ character.min : int [1:21] NA NA NA NA NA NA NA 1 2 3 ...
#> $ character.max : int [1:21] NA NA NA NA NA NA NA 132 4 38 ...
#> $ character.empty : int [1:21] NA NA NA NA NA NA NA 0 0 0 ...
#> $ character.n_unique : int [1:21] NA NA NA NA NA NA NA 11562 31 580 ...
#> $ character.whitespace: int [1:21] NA NA NA NA NA NA NA 0 0 0 ...
#> $ numeric.mean : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.sd : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.p0 : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.p25 : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.p50 : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.p75 : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.p100 : num [1:21] NA NA NA NA NA NA NA NA NA NA ...
#> $ numeric.hist : chr [1:21] NA NA NA NA ...
#> - attr(*, "data_rows")= int 16719
#> - attr(*, "data_cols")= int 21
#> - attr(*, "df_name")= chr "`df`"
#> - attr(*, "dt_key")= logi NA
#> - attr(*, "groups")= list()
#> - attr(*, "base_skimmers")= chr [1:2] "n_missing" "complete_rate"
#> - attr(*, "skimmers_used")=List of 3
#> ..$ character: chr [1:5] "min" "max" "empty" "n_unique" ...
#> ..$ numeric : chr [1:8] "mean" "sd" "p0" "p25" ...
#> ..$ factor : chr [1:3] "ordered" "n_unique" "top_counts"
Kdybychom htěli deskriptivní statistiky jen pro některé proměnné,
můžeme si je dopředu vybrat pomocí funkce select()
anebo je
uvést, až v samotné funkci skim()
. V ní můžeme totiž
provádět výběr proměnných (sloupců) podobně jako ve funkci
select()
.
skim(df, ends_with("sales"))
#> ── Data Summary ────────────────────────
#> Values
#> Name df
#> Number of rows 16719
#> Number of columns 21
#> _______________________
#> Column type frequency:
#> numeric 5
#> ________________________
#> Group variables None
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100
#> 1 na_sales 0 1 0.263 0.814 0 0 0.08 0.24 41.4
#> 2 eu_sales 0 1 0.145 0.503 0 0 0.02 0.11 29.0
#> 3 jp_sales 0 1 0.0776 0.309 0 0 0 0.04 10.2
#> 4 other_sales 0 1 0.0473 0.187 0 0 0.01 0.03 10.6
#> 5 global_sales 0 1 0.534 1.55 0.01 0.06 0.17 0.47 82.5
#> hist
#> 1 ▇▁▁▁▁
#> 2 ▇▁▁▁▁
#> 3 ▇▁▁▁▁
#> 4 ▇▁▁▁▁
#> 5 ▇▁▁▁▁
Výstup s výsledky má podobu dataframu s dodatečnými atributy (např. počtem řádků a sloupců) a dvěma sloupci obsahující metadata o proměnných:
Objekt vytvořený funkcí skim (který jsme si pojmenovali
data_summary
) má “třídu” skim_df (obecně mu můžeme říkat
skim_df objekt) a můžeme jej pomocí pipe operátoru snadno poslat do
další funkce, např. filter, a vybrat pouze informace o proměnných, které
mají v názvu “sales”.
Dejte si pozor na to, že proměnné jsou ve skim_df objektu
reprezentovány řádky, zatímco typ informace či statistik je
reprezentován sloupci, proto k výběru proměnných používáme
filter()
a k výběru typu informací/statistik
select()
. V příkladu níže jsme si navíc pomohli funkcí
str_detect()
, která vrací hodnotu TRUE
, pokud
prvek dané proměnné obsahuje zadaný řetězec znaků.
class(data_summary)
#> [1] "skim_df" "tbl_df" "tbl" "data.frame"
%>%
data_summary filter(str_detect(skim_variable, "sales"))
#> ── Data Summary ────────────────────────
#> Values
#> Name df
#> Number of rows 16719
#> Number of columns 21
#> _______________________
#> Column type frequency:
#> numeric 5
#> ________________________
#> Group variables None
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100
#> 1 na_sales 0 1 0.263 0.814 0 0 0.08 0.24 41.4
#> 2 eu_sales 0 1 0.145 0.503 0 0 0.02 0.11 29.0
#> 3 jp_sales 0 1 0.0776 0.309 0 0 0 0.04 10.2
#> 4 other_sales 0 1 0.0473 0.187 0 0 0.01 0.03 10.6
#> 5 global_sales 0 1 0.534 1.55 0.01 0.06 0.17 0.47 82.5
#> hist
#> 1 ▇▁▁▁▁
#> 2 ▇▁▁▁▁
#> 3 ▇▁▁▁▁
#> 4 ▇▁▁▁▁
#> 5 ▇▁▁▁▁
Podobně můžeme vybrat např. pouze numerické proměnné a ze statistik pak pouze průměry a směrodatné odchylky
%>%
data_summary filter(skim_type == "numeric") %>%
select(skim_variable, numeric.mean, numeric.sd)
#> # A tibble: 10 × 3
#> skim_variable numeric.mean numeric.sd
#> <chr> <dbl> <dbl>
#> 1 year_of_release 2006. 5.88
#> 2 na_sales 0.263 0.814
#> 3 eu_sales 0.145 0.503
#> 4 jp_sales 0.0776 0.309
#> 5 other_sales 0.0473 0.187
#> 6 global_sales 0.534 1.55
#> 7 critic_score 69.0 13.9
#> 8 critic_count 26.4 19.0
#> 9 user_score 7.13 1.50
#> 10 user_count 162. 561.
Do funkce skim také můžeme vložit dataset rozdělený do skupin pomocí
funkce group_by()
. V takovém případě se nám vypočtou
statistiky pro jednotlivé skupiny a do výstupního skim_df objektu
přibude sloupec udávající skupinu (groping variable). V příkladu níže
přibyl sloupec genre
.
%>%
df group_by(genre) %>%
select(genre, critic_score) %>%
skim() %>%
arrange(desc(numeric.mean))
#> ── Data Summary ────────────────────────
#> Values
#> Name Piped data
#> Number of rows 16719
#> Number of columns 2
#> _______________________
#> Column type frequency:
#> numeric 1
#> ________________________
#> Group variables genre
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable genre n_missing complete_rate mean sd p0 p25 p50 p75
#> 1 critic_score Role-Playing 763 0.491 72.7 12.0 35 65 74 82
#> 2 critic_score Strategy 381 0.442 72.1 11.8 35 65 73 80
#> 3 critic_score Sports 1154 0.509 72.0 13.9 19 64 75 82
#> 4 critic_score Shooter 379 0.714 70.2 14.6 22 61 73 81
#> 5 critic_score Fighting 440 0.482 69.2 14.3 23 61 72 80
#> 6 critic_score Simulation 522 0.403 68.6 12.4 31 62 70 77
#> 7 critic_score Platform 391 0.560 68.1 13.2 19 59 69 77
#> 8 critic_score Racing 507 0.594 68.0 14.2 13 59 69 79
#> 9 critic_score Puzzle 356 0.386 67.4 12.7 25 60.8 70 76
#> 10 critic_score Action 1480 0.561 66.6 14.2 19 57 68 77
#> 11 critic_score Misc 1227 0.299 66.6 14.2 19 58.5 69 77
#> 12 critic_score Adventure 980 0.248 65.3 13.9 17 57 66 76
#> 13 critic_score <NA> 2 0 NaN NA NA NA NA NA
#> p100 hist
#> 1 96 "▁▂▆▇▅"
#> 2 94 "▁▂▆▇▃"
#> 3 98 "▁▁▃▇▃"
#> 4 97 "▁▂▃▇▃"
#> 5 98 "▁▂▅▇▂"
#> 6 92 "▁▂▆▇▅"
#> 7 97 "▁▂▆▇▃"
#> 8 96 "▁▁▅▇▅"
#> 9 90 "▁▂▅▇▃"
#> 10 98 "▁▂▆▇▂"
#> 11 93 "▁▂▅▇▃"
#> 12 93 "▁▂▅▇▅"
#> 13 NA " "
Dále balíček skimr nabízí funkci
skim_tee()
. Ta funguje velmi podobně jako
skim()
, ale s tím rozdílem, že jejím skutečným výstupem je
původní dataframe, nikoli tabulka s deskriptivními statistikami. Ta
putuje jen do konzole. Toho můžeme použít v případě, kdy deskriptivní
statistiky nepotřebujeme uložit, ale jen vytisknout do konzole, a
zároveň chceme původní dataset využít v jakékoli další funkci, např. pro
tvorbu grafu.
%>%
df skim_tee(critic_score, user_score) %>%
ggplot(aes(critic_score, user_score)) +
geom_point()
#> ── Data Summary ────────────────────────
#> Values
#> Name data
#> Number of rows 16719
#> Number of columns 21
#> _______________________
#> Column type frequency:
#> numeric 2
#> ________________________
#> Group variables None
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
#> 1 critic_score 8582 0.487 69.0 13.9 13 60 71 79 98 ▁▁▅▇▃
#> 2 user_score 9129 0.454 7.13 1.50 0 6.4 7.5 8.2 9.7 ▁▁▂▇▇
K podrobnější úpravě výstupu z funkce skim slouží další dvě funce.
Nejprve si ukážeme funkci partition()
. Ta vrátí objekt typu
list, jehož prvky tvoří několik dataframes (podle typu proměnné:
"factor"
, "character"
, "numeric"
)
se statistikami.
<- df %>%
data_summary skim() %>%
partition()
glimpse(data_summary)
#> List of 3
#> $ factor : one_skim_df [7 × 6] (S3: one_skim_df/tbl_df/tbl/data.frame)
#> ..$ skim_variable: chr [1:7] "genre" "rating" "post_2010" "decade" ...
#> ..$ n_missing : int [1:7] 2 6769 0 269 0 0 0
#> ..$ complete_rate: num [1:7] 1 0.595 1 0.984 1 ...
#> ..$ ordered : logi [1:7] FALSE FALSE FALSE FALSE FALSE FALSE ...
#> ..$ n_unique : int [1:7] 12 5 2 4 5 8 2
#> ..$ top_counts : chr [1:7] "Act: 3370, Spo: 2348, Mis: 1750, Rol: 1500" "E/1: 5411, T: 2961, M/A: 1564, EC/: 11" "No: 11169, Yes: 5550" "200: 9193, 201: 5281, 199: 1771, 198: 205" ...
#> ..- attr(*, "data_rows")= int 16719
#> ..- attr(*, "data_cols")= int 21
#> ..- attr(*, "df_name")= chr "`.`"
#> ..- attr(*, "dt_key")= logi NA
#> ..- attr(*, "groups")= list()
#> ..- attr(*, "base_skimmers")= chr [1:2] "n_missing" "complete_rate"
#> ..- attr(*, "skimmers_used")=List of 3
#> ..- attr(*, "skim_type")= chr "factor"
#> $ character: one_skim_df [4 × 8] (S3: one_skim_df/tbl_df/tbl/data.frame)
#> ..$ skim_variable: chr [1:4] "name" "platform" "publisher" "developer"
#> ..$ n_missing : int [1:4] 2 0 54 6623
#> ..$ complete_rate: num [1:4] 1 1 0.997 0.604
#> ..$ min : int [1:4] 1 2 3 2
#> ..$ max : int [1:4] 132 4 38 80
#> ..$ empty : int [1:4] 0 0 0 0
#> ..$ n_unique : int [1:4] 11562 31 580 1696
#> ..$ whitespace : int [1:4] 0 0 0 0
#> ..- attr(*, "data_rows")= int 16719
#> ..- attr(*, "data_cols")= int 21
#> ..- attr(*, "df_name")= chr "`.`"
#> ..- attr(*, "dt_key")= logi NA
#> ..- attr(*, "groups")= list()
#> ..- attr(*, "base_skimmers")= chr [1:2] "n_missing" "complete_rate"
#> ..- attr(*, "skimmers_used")=List of 3
#> ..- attr(*, "skim_type")= chr "character"
#> $ numeric : one_skim_df [10 × 11] (S3: one_skim_df/tbl_df/tbl/data.frame)
#> ..$ skim_variable: chr [1:10] "year_of_release" "na_sales" "eu_sales" "jp_sales" ...
#> ..$ n_missing : int [1:10] 269 0 0 0 0 0 8582 8582 9129 9129
#> ..$ complete_rate: num [1:10] 0.984 1 1 1 1 ...
#> ..$ mean : num [1:10] 2.01e+03 2.63e-01 1.45e-01 7.76e-02 4.73e-02 ...
#> ..$ sd : num [1:10] 5.879 0.814 0.503 0.309 0.187 ...
#> ..$ p0 : num [1:10] 1980 0 0 0 0 0.01 13 3 0 4
#> ..$ p25 : num [1:10] 2003 0 0 0 0 ...
#> ..$ p50 : num [1:10] 2007 0.08 0.02 0 0.01 ...
#> ..$ p75 : num [1:10] 2010 0.24 0.11 0.04 0.03 0.47 79 36 8.2 81
#> ..$ p100 : num [1:10] 2020 41.4 29 10.2 10.6 ...
#> ..$ hist : chr [1:10] "▁▁▃▇▂" "▇▁▁▁▁" "▇▁▁▁▁" "▇▁▁▁▁" ...
#> ..- attr(*, "data_rows")= int 16719
#> ..- attr(*, "data_cols")= int 21
#> ..- attr(*, "df_name")= chr "`.`"
#> ..- attr(*, "dt_key")= logi NA
#> ..- attr(*, "groups")= list()
#> ..- attr(*, "base_skimmers")= chr [1:2] "n_missing" "complete_rate"
#> ..- attr(*, "skimmers_used")=List of 3
#> ..- attr(*, "skim_type")= chr "numeric"
#> - attr(*, "class")= chr [1:2] "skim_list" "list"
#> - attr(*, "data_rows")= int 16719
#> - attr(*, "data_cols")= int 21
#> - attr(*, "df_name")= chr "`.`"
#> - attr(*, "dt_key")= logi NA
#> - attr(*, "groups")= list()
#> - attr(*, "base_skimmers")= chr [1:2] "n_missing" "complete_rate"
#> - attr(*, "skimmers_used")=List of 3
#> ..$ character: chr [1:5] "min" "max" "empty" "n_unique" ...
#> ..$ numeric : chr [1:8] "mean" "sd" "p0" "p25" ...
#> ..$ factor : chr [1:3] "ordered" "n_unique" "top_counts"
$factor data_summary
#>
#> ── Variable type: factor ───────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate ordered n_unique top_counts
#> 1 genre 2 1.00 FALSE 12 Act: 3370, Spo: 2348, …
#> 2 rating 6769 0.595 FALSE 5 E/1: 5411, T: 2961, M/…
#> 3 post_2010 0 1 FALSE 2 No: 11169, Yes: 5550
#> 4 decade 269 0.984 FALSE 4 200: 9193, 201: 5281, …
#> 5 platform_type 0 1 FALSE 5 Pla: 6723, Nin: 6271, …
#> 6 generation 0 1 FALSE 8 7th: 7274, 6th: 4415, …
#> 7 handheld 0 1 FALSE 2 No: 10923, Yes: 5796
$character data_summary
#>
#> ── Variable type: character ────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate min max empty n_unique whitespace
#> 1 name 2 1.00 1 132 0 11562 0
#> 2 platform 0 1 2 4 0 31 0
#> 3 publisher 54 0.997 3 38 0 580 0
#> 4 developer 6623 0.604 2 80 0 1696 0
$numeric data_summary
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_mis…¹ compl…² mean sd p0 p25 p50 p75
#> 1 year_of_rele… 269 0.984 2.01e+3 5.88 1980 2003 2007 2010
#> 2 na_sales 0 1 2.63e-1 0.814 0 0 0.08 0.24
#> 3 eu_sales 0 1 1.45e-1 0.503 0 0 0.02 0.11
#> 4 jp_sales 0 1 7.76e-2 0.309 0 0 0 0.04
#> 5 other_sales 0 1 4.73e-2 0.187 0 0 0.01 0.03
#> 6 global_sales 0 1 5.34e-1 1.55 0.01 0.06 0.17 0.47
#> 7 critic_score 8582 0.487 6.90e+1 13.9 13 60 71 79
#> 8 critic_count 8582 0.487 2.64e+1 19.0 3 12 21 36
#> 9 user_score 9129 0.454 7.13e+0 1.50 0 6.4 7.5 8.2
#> 10 user_count 9129 0.454 1.62e+2 561. 4 10 24 81
#> # … with 2 more variables: p100 <dbl>, hist <chr>, and abbreviated variable
#> # names ¹n_missing, ²complete_rate
Alternativně můžeme použít funkci yank()
k výběru
proměnných pouze určitého typu. Ostatní typy proměnných jsou
vyřazeny.
<- df %>%
data_summary skim() %>%
yank("factor")
data_summary
#>
#> ── Variable type: factor ───────────────────────────────────────────────────────
#> skim_variable n_missing complete_rate ordered n_unique top_counts
#> 1 genre 2 1.00 FALSE 12 Act: 3370, Spo: 2348, …
#> 2 rating 6769 0.595 FALSE 5 E/1: 5411, T: 2961, M/…
#> 3 post_2010 0 1 FALSE 2 No: 11169, Yes: 5550
#> 4 decade 269 0.984 FALSE 4 200: 9193, 201: 5281, …
#> 5 platform_type 0 1 FALSE 5 Pla: 6723, Nin: 6271, …
#> 6 generation 0 1 FALSE 8 7th: 7274, 6th: 4415, …
#> 7 handheld 0 1 FALSE 2 No: 10923, Yes: 5796
I kdybychom k výběru statistik mohli použít funkci
select()
, lepší je použít funkci focus()
,
protože funkce select()
vede k odstranění užitečných
metadat z objejtu skim_df, zatímco focus()
vždy tato
metadata zachová.
<- df %>%
data_summary skim() %>%
focus(n_missing, numeric.mean) %>%
yank("numeric")
data_summary
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_missing mean
#> 1 year_of_release 269 2006.
#> 2 na_sales 0 0.263
#> 3 eu_sales 0 0.145
#> 4 jp_sales 0 0.0776
#> 5 other_sales 0 0.0473
#> 6 global_sales 0 0.534
#> 7 critic_score 8582 69.0
#> 8 critic_count 8582 26.4
#> 9 user_score 9129 7.13
#> 10 user_count 9129 162.
Samozřejmě se také může stát, že chceme vypočíst jiné než defaultní
statistiky. K tomu se používá funkce skim_with()
do které
specifikujeme, jaké dodatečné statistiky chceme vypočíst, pro které typy
proměnných a jak se mají jmenovat. Typ proměnné může být
base
(statistika se počítá pro všechny typy),
factor
, character
a numeric
.
<- skim_with(
my_skim # Pro všechny typy proměnných vypočítáme počet validních hodnot
base = sfl(
n_valid = ~sum(!is.na(.))
),# Pro numerické proměnné vypočteme navíc šikmost a špičatost
numeric = sfl(
skew = ~skewness(., na.rm = TRUE),
kurt = ~kurtosis(., na.rm = TRUE)
)
)# ~NAZEV_FUNKCE(TEČKA_JAKO_PLACEHOLDER_PRO_PROMĚNNÉ, DODATEČNÉ_ARGUMENTY)
# Tím jsme definovali svou vlastní funkci my_skim() a můžeme ji použít
# stejně jako skim()
%>%
df my_skim()
#> ── Data Summary ────────────────────────
#> Values
#> Name Piped data
#> Number of rows 16719
#> Number of columns 21
#> _______________________
#> Column type frequency:
#> factor 7
#> character 4
#> numeric 10
#> ________________________
#> Group variables None
#>
#> ── Variable type: factor ───────────────────────────────────────────────────────
#> skim_variable n_valid ordered n_unique
#> 1 genre 16717 FALSE 12
#> 2 rating 9950 FALSE 5
#> 3 post_2010 16719 FALSE 2
#> 4 decade 16450 FALSE 4
#> 5 platform_type 16719 FALSE 5
#> 6 generation 16719 FALSE 8
#> 7 handheld 16719 FALSE 2
#> top_counts
#> 1 Act: 3370, Spo: 2348, Mis: 1750, Rol: 1500
#> 2 E/1: 5411, T: 2961, M/A: 1564, EC/: 11
#> 3 No: 11169, Yes: 5550
#> 4 200: 9193, 201: 5281, 199: 1771, 198: 205
#> 5 Pla: 6723, Nin: 6271, XBo: 2333, PC: 974
#> 6 7th: 7274, 6th: 4415, 8th: 1739, 5th: 1699
#> 7 No: 10923, Yes: 5796
#>
#> ── Variable type: character ────────────────────────────────────────────────────
#> skim_variable n_valid min max empty n_unique whitespace
#> 1 name 16717 1 132 0 11562 0
#> 2 platform 16719 2 4 0 31 0
#> 3 publisher 16665 3 38 0 580 0
#> 4 developer 10096 2 80 0 1696 0
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_valid mean sd p0 p25 p50 p75
#> 1 year_of_release 16450 2006. 5.88 1980 2003 2007 2010
#> 2 na_sales 16719 0.263 0.814 0 0 0.08 0.24
#> 3 eu_sales 16719 0.145 0.503 0 0 0.02 0.11
#> 4 jp_sales 16719 0.0776 0.309 0 0 0 0.04
#> 5 other_sales 16719 0.0473 0.187 0 0 0.01 0.03
#> 6 global_sales 16719 0.534 1.55 0.01 0.06 0.17 0.47
#> 7 critic_score 8137 69.0 13.9 13 60 71 79
#> 8 critic_count 8137 26.4 19.0 3 12 21 36
#> 9 user_score 7590 7.13 1.50 0 6.4 7.5 8.2
#> 10 user_count 7590 162. 561. 4 10 24 81
#> p100 hist skew kurt
#> 1 2020 ▁▁▃▇▂ -0.973 4.77
#> 2 41.4 ▇▁▁▁▁ 18.8 652.
#> 3 29.0 ▇▁▁▁▁ 18.9 758.
#> 4 10.2 ▇▁▁▁▁ 11.2 197.
#> 5 10.6 ▇▁▁▁▁ 24.6 1058.
#> 6 82.5 ▇▁▁▁▁ 17.4 607.
#> 7 98 ▁▁▅▇▃ -0.614 3.14
#> 8 113 ▇▃▂▁▁ 1.15 4.03
#> 9 9.7 ▁▁▂▇▇ -1.25 4.72
#> 10 10665 ▇▁▁▁▁ 9.03 115.
Defaultní chování skim_with()
je takové, že nové
statistiky jsou doplněny k těm původním. Kdyby nám to nevyhovovalo,
můžeme to změnit pomocí argumentu append = FALSE
. Původní
statistiky jsou tím odstraněny, ale jen u toho typu proměnných, u něhož
explicitně specifikujeme statistiky nové (tj. kromě base
),
jak si můžeme všimnout níže.
<- skim_with(
my_skim base = sfl(
n_valid = ~sum(!is.na(.))
),numeric = sfl(
median = ~median(., na.rm = TRUE),
IQR = ~IQR(., na.rm = TRUE)),
append = FALSE)
my_skim(df)
#> ── Data Summary ────────────────────────
#> Values
#> Name df
#> Number of rows 16719
#> Number of columns 21
#> _______________________
#> Column type frequency:
#> factor 7
#> character 4
#> numeric 10
#> ________________________
#> Group variables None
#>
#> ── Variable type: factor ───────────────────────────────────────────────────────
#> skim_variable n_valid ordered n_unique
#> 1 genre 16717 FALSE 12
#> 2 rating 9950 FALSE 5
#> 3 post_2010 16719 FALSE 2
#> 4 decade 16450 FALSE 4
#> 5 platform_type 16719 FALSE 5
#> 6 generation 16719 FALSE 8
#> 7 handheld 16719 FALSE 2
#> top_counts
#> 1 Act: 3370, Spo: 2348, Mis: 1750, Rol: 1500
#> 2 E/1: 5411, T: 2961, M/A: 1564, EC/: 11
#> 3 No: 11169, Yes: 5550
#> 4 200: 9193, 201: 5281, 199: 1771, 198: 205
#> 5 Pla: 6723, Nin: 6271, XBo: 2333, PC: 974
#> 6 7th: 7274, 6th: 4415, 8th: 1739, 5th: 1699
#> 7 No: 10923, Yes: 5796
#>
#> ── Variable type: character ────────────────────────────────────────────────────
#> skim_variable n_valid min max empty n_unique whitespace
#> 1 name 16717 1 132 0 11562 0
#> 2 platform 16719 2 4 0 31 0
#> 3 publisher 16665 3 38 0 580 0
#> 4 developer 10096 2 80 0 1696 0
#>
#> ── Variable type: numeric ──────────────────────────────────────────────────────
#> skim_variable n_valid median IQR
#> 1 year_of_release 16450 2007 7
#> 2 na_sales 16719 0.08 0.24
#> 3 eu_sales 16719 0.02 0.11
#> 4 jp_sales 16719 0 0.04
#> 5 other_sales 16719 0.01 0.03
#> 6 global_sales 16719 0.17 0.41
#> 7 critic_score 8137 71 19
#> 8 critic_count 8137 21 24
#> 9 user_score 7590 7.5 1.80
#> 10 user_count 7590 24 71
Balíček dlookr slouží k diagnostice dat. Začít
můžeme např. funkcí diagnose()
, která slouží k přehledu
chybějících a jedinečných hodnot. Prvním argumentem je použitý dataframe
a dalšími argumenty si můžeme vybrat proměnné podobně jako ve funkci
select()
.
diagnose(df)
#> # A tibble: 21 × 6
#> variables types missing_count missing_percent unique_count unique…¹
#> <chr> <chr> <int> <dbl> <int> <dbl>
#> 1 name character 2 0.0120 11563 0.692
#> 2 platform character 0 0 31 0.00185
#> 3 year_of_release numeric 269 1.61 40 0.00239
#> 4 genre factor 2 0.0120 13 0.000778
#> 5 publisher character 54 0.323 581 0.0348
#> 6 na_sales numeric 0 0 402 0.0240
#> 7 eu_sales numeric 0 0 307 0.0184
#> 8 jp_sales numeric 0 0 244 0.0146
#> 9 other_sales numeric 0 0 155 0.00927
#> 10 global_sales numeric 0 0 629 0.0376
#> # … with 11 more rows, and abbreviated variable name ¹unique_rate
diagnose(df, ends_with("sales"))
#> # A tibble: 5 × 6
#> variables types missing_count missing_percent unique_count unique_rate
#> <chr> <chr> <int> <dbl> <int> <dbl>
#> 1 na_sales numeric 0 0 402 0.0240
#> 2 eu_sales numeric 0 0 307 0.0184
#> 3 jp_sales numeric 0 0 244 0.0146
#> 4 other_sales numeric 0 0 155 0.00927
#> 5 global_sales numeric 0 0 629 0.0376
diagnose(df, rating, platform, name)
#> # A tibble: 3 × 6
#> variables types missing_count missing_percent unique_count unique_rate
#> <chr> <chr> <int> <dbl> <int> <dbl>
#> 1 rating factor 6769 40.5 6 0.000359
#> 2 platform character 0 0 31 0.00185
#> 3 name character 2 0.0120 11563 0.692
Funkce balíčku dlookr můžeme pipovat do dalších funkcí a tím s výstupem dále pracovat. Např. vybrat pouze proměnné s chybějícími hodnotami a seřadit je sestupně právě podle počtu chybějících hodnot
%>%
df diagnose() %>%
filter(missing_count > 0) %>%
arrange(desc(missing_count))
#> # A tibble: 11 × 6
#> variables types missing_count missing_percent unique_count unique…¹
#> <chr> <chr> <int> <dbl> <int> <dbl>
#> 1 user_score numeric 9129 54.6 96 0.00574
#> 2 user_count numeric 9129 54.6 889 0.0532
#> 3 critic_score numeric 8582 51.3 83 0.00496
#> 4 critic_count numeric 8582 51.3 107 0.00640
#> 5 rating factor 6769 40.5 6 0.000359
#> 6 developer character 6623 39.6 1697 0.102
#> 7 year_of_release numeric 269 1.61 40 0.00239
#> 8 decade factor 269 1.61 5 0.000299
#> 9 publisher character 54 0.323 581 0.0348
#> 10 name character 2 0.0120 11563 0.692
#> 11 genre factor 2 0.0120 13 0.000778
#> # … with abbreviated variable name ¹unique_rate
Funkce diagnose_numeric()
diagnostikuje numerické
proměnné (tj. proměnné typu integer
a double
)
v daném datasetu, ale na rozdíl od funkce diagnose()
poskytuje více informací.
diagnose_numeric(df)
#> # A tibble: 10 × 10
#> variables min Q1 mean median Q3 max zero minus outlier
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <int> <int>
#> 1 year_of_r… 1980 2003 2.01e+3 2007 2010 2.02e3 0 0 305
#> 2 na_sales 0 0 2.63e-1 0.08 0.24 4.14e1 4511 0 1687
#> 3 eu_sales 0 0 1.45e-1 0.02 0.11 2.90e1 5874 0 2061
#> 4 jp_sales 0 0 7.76e-2 0 0.04 1.02e1 10515 0 2434
#> 5 other_sal… 0 0 4.73e-2 0.01 0.03 1.06e1 6604 0 2243
#> 6 global_sa… 0.01 0.06 5.34e-1 0.17 0.47 8.25e1 0 0 1892
#> 7 critic_sc… 13 60 6.90e+1 71 79 9.8 e1 0 0 83
#> 8 critic_co… 3 12 2.64e+1 21 36 1.13e2 0 0 251
#> 9 user_score 0 6.4 7.13e+0 7.5 8.2 9.7 e0 1 0 305
#> 10 user_count 4 10 1.62e+2 24 81 1.07e4 0 0 1080
Funkce diagnose_category()
sloužít slouží k diagnostice
kategorických proměnných (včetně factor
a
character
). Pokud je počet úrovní velký, můžeme pomocí
argumentu top
specifikovat, ať se nám zobrazí pouze
četnosti pro nejvíce zastoupené kategorie, např. prvních pět:
diagnose_category(df, top = 5)
#> # A tibble: 49 × 6
#> variables levels N freq ratio rank
#> <chr> <chr> <int> <int> <dbl> <int>
#> 1 name Need for Speed: Most Wanted 16719 12 0.0718 1
#> 2 name FIFA 14 16719 9 0.0538 2
#> 3 name LEGO Marvel Super Heroes 16719 9 0.0538 2
#> 4 name Madden NFL 07 16719 9 0.0538 2
#> 5 name Ratatouille 16719 9 0.0538 2
#> 6 platform PS2 16719 2161 12.9 1
#> 7 platform DS 16719 2152 12.9 2
#> 8 platform PS3 16719 1331 7.96 3
#> 9 platform Wii 16719 1320 7.90 4
#> 10 platform X360 16719 1262 7.55 5
#> # … with 39 more rows
Funkce diagnose_outlier()
slouží k diagnostice
extrémních případů, identifikovaných na základě pravidla boxplotu
(hodnot odchylujících se více než 1,5násobek mezikvartilového rozpětí od
1. a 3. kvartilu směrem k bližšímu konci distribuce). Zobrazí nám počet
a podíl outlierů, jejich průměr a průměr proměnných bez outlierů a s
nimi.
diagnose_outlier(df)
#> # A tibble: 10 × 6
#> variables outliers_cnt outliers_ratio outliers_mean with_mean without…¹
#> <chr> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 year_of_release 305 1.82 1986. 2006. 2007.
#> 2 na_sales 1687 10.1 1.62 0.263 0.111
#> 3 eu_sales 2061 12.3 0.873 0.145 0.0427
#> 4 jp_sales 2434 14.6 0.471 0.0776 0.0106
#> 5 other_sales 2243 13.4 0.267 0.0473 0.0133
#> 6 global_sales 1892 11.3 2.92 0.534 0.229
#> 7 critic_score 83 0.496 26.2 69.0 69.4
#> 8 critic_count 251 1.50 82.1 26.4 24.6
#> 9 user_score 305 1.82 2.75 7.13 7.31
#> 10 user_count 1080 6.46 929. 162. 35.1
#> # … with abbreviated variable name ¹without_mean
Funkce plot_outlier()
pak slouží k zobrazení distribuce
s outliery a bez nich pomocí boxplotu a histogramu.
plot_outlier(df, global_sales)
Bohužel funkce diagnose_numeric()
nedodržuje rozdělení
datasetu pomocí funkce group_by()
, ale
dlookr má také funkci describe()
,
která to dovede.
%>%
df group_by(post_2010) %>%
describe() %>%
mutate(across(where(is.numeric), round, digits = 2))
#> # A tibble: 20 × 27
#> described…¹ post_…² n na mean sd se_mean IQR skewn…³ kurto…⁴
#> <chr> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 critic_cou… No 5671 5498 24.3 16.8 0.22 22 1.19 1.3
#> 2 critic_cou… Yes 2466 3084 31.0 22.6 0.45 34 0.86 0.01
#> 3 critic_sco… No 5671 5498 68.4 14.0 0.19 19 -0.55 0.08
#> 4 critic_sco… Yes 2466 3084 70.3 13.7 0.28 18 -0.77 0.38
#> 5 eu_sales No 11169 0 0.14 0.53 0 0.1 22.4 930.
#> 6 eu_sales Yes 5550 0 0.16 0.46 0.01 0.12 7.59 81.8
#> 7 global_sal… No 11169 0 0.56 1.69 0.02 0.43 18.6 626.
#> 8 global_sal… Yes 5550 0 0.48 1.21 0.02 0.35 7.53 80.2
#> 9 jp_sales No 11169 0 0.09 0.34 0 0.03 10.4 170.
#> 10 jp_sales Yes 5550 0 0.06 0.22 0 0.04 12.8 221.
#> 11 na_sales No 11169 0 0.29 0.9 0.01 0.25 19.5 638.
#> 12 na_sales Yes 5550 0 0.21 0.61 0.01 0.18 8.92 127.
#> 13 other_sales No 11169 0 0.05 0.2 0 0.03 26.7 1104.
#> 14 other_sales Yes 5550 0 0.05 0.15 0 0.04 9.56 151.
#> 15 user_count No 4964 6205 86.6 356. 5.05 37 13.1 249.
#> 16 user_count Yes 2626 2924 305. 800. 15.6 198 6.41 55.4
#> 17 user_score No 4964 6205 7.35 1.44 0.02 1.7 -1.47 2.68
#> 18 user_score Yes 2626 2924 6.7 1.52 0.03 1.9 -1.02 0.87
#> 19 year_of_re… No 11169 0 2004. 4.99 0.05 7 -1.56 3.44
#> 20 year_of_re… Yes 5281 269 2012. 2.04 0.03 3 0.43 -1.15
#> # … with 17 more variables: p00 <dbl>, p01 <dbl>, p05 <dbl>, p10 <dbl>,
#> # p20 <dbl>, p25 <dbl>, p30 <dbl>, p40 <dbl>, p50 <dbl>, p60 <dbl>,
#> # p70 <dbl>, p75 <dbl>, p80 <dbl>, p90 <dbl>, p95 <dbl>, p99 <dbl>,
#> # p100 <dbl>, and abbreviated variable names ¹described_variables,
#> # ²post_2010, ³skewness, ⁴kurtosis
Funkce normality()
provádí Shapiro-Wilkův test normality
dat. U tak velkého vzorku, jako máme by, si můžeme být téměř jisti, že
bude test signifikantní, i kdyby odchylka od normality byla minimální.
Obecně nás spíš může zajímá samotná testová statistika, která nabývá
hodnot od 0 do 1 a udává, jak těsně se naše data shodují s normálně
rozdělenou proměnnou.
normality(df, contains("sales")) %>%
arrange(statistic)
#> # A tibble: 5 × 4
#> vars statistic p_value sample
#> <chr> <dbl> <dbl> <dbl>
#> 1 other_sales 0.219 4.34e-90 5000
#> 2 jp_sales 0.237 1.48e-89 5000
#> 3 na_sales 0.277 2.48e-88 5000
#> 4 eu_sales 0.279 2.98e-88 5000
#> 5 global_sales 0.283 3.82e-88 5000
Pomocí funkce plot_normality()
si pak můžeme nechat
zobrazit histogram a Q-Q graf původních hodnot a dva histogramy
(left
a right
) hodnot po transformaci. V
nápovědě k funkci ?plot_normality
je přehled všech
tranformací, které můžeme specikovat argumenty left
a
right
.
plot_normality(df, global_sales,
left = "1/x", right = "log")
Funkce normality()
i plot_normality()
navíc
podporují rozdělení datasetu pomocí group_by()
.
%>%
df group_by(decade) %>%
normality(global_sales) %>%
arrange(statistic)
#> # A tibble: 5 × 5
#> variable decade statistic p_value sample
#> <chr> <fct> <dbl> <dbl> <dbl>
#> 1 global_sales 2000s 0.277 2.52e-88 5000
#> 2 global_sales 1980s 0.327 7.25e-27 205
#> 3 global_sales 2010s 0.366 2.37e-85 5000
#> 4 global_sales 1990s 0.388 9.21e-61 1771
#> 5 global_sales <NA> 0.567 2.32e-25 269
%>%
df group_by(post_2010) %>%
plot_normality(global_sales,
left = "sqrt", right = "log")
Pro tvorbu exploračních grafů jsem vytvořil několik funkcí, které
umožňují snadno vytvořit i několik grafů najednou. Všechny funkce mají
jako první argument použitý dataset. Jejich názvy načínají slovem
plot_
, pak následuje typ grafu, např. bar
. V
případě, že se jedná o funkci, která dovede vytvořit více grafů zároveň,
končí příponou _mult
.
Funkce plot_bar()
vytváří jeden sloupcový graf a má tyto
argumenty:
data
: použitý dataset.var
: četnosti které proměnné chceme zjistit
(character).fill
: nastavení výplňě podle další proměnné
(character).facet
: fazetovat graf podle další
proměnné¨(character).add_n
: přidat labely s absolutními četnostmi
(logical).sort
: seřadit sloupce podle četností (logical)?Funkce plot_bar_mult()
vytváří více sloupcových grafů a
má stejné argumenty jako funkce plot_bar()
, ale umožňuje do
argumentu var
vložit více názvů proměnných (jako textový
vektor).
plot_bar(df, var = "genre", fill = "decade", facet = "handheld")
plot_bar_mult(data = df, var = c("decade", "genre", "rating"),
sort = FALSE)
#> [[1]]
#>
#> [[2]]
#>
#> [[3]]
Pro tvorbu skládaných sloupcových grafů můžete využít funkce
plot_stackbar()
, která vytváří jeden skládanýc sloupcový
graf a `plot_stackbar_mult()`` pro tvorbu více sloupcových grafů
zároveň. Mají tyto argumenty:
data
: použitý dataset.var
: četnosti které proměnné chceme zjistit
(character).fill
: nastavení výplňě podle další proměnné
(character).facet
: fazetovat graf podle další
proměnné¨(character).plot_stackbar(df, var = "handheld", fill = "genre")
plot_stackbar_mult(df, var = c("handheld", "decade"), fill = c("rating", "genre"))
#> [[1]]
#>
#> [[2]]
Pro tvorbu histogramu můžeme použít funkce
plot_histogram()
a plot_histogram_mult()
,
které mají tyto argumenty:
data
: použitý dataset.var
: zobrazená proměnná (character).facet
: fazetovat graf podle další
proměnné¨(character).geom
: "hist"
pro histogram,
"density"
pro graf hustoty pravděpodobnosti, nebo
"freqpoly"
pro frekvenční polygon.transform_fun
: funkce použitý k případné transformaci
hodnotplot_histogram(df, "critic_score")
plot_histogram(df, "critic_score", geom = "density")
plot_histogram(df, "critic_score", geom = "freqpoly")
plot_histogram(df, var = "global_sales",
facet = "platform_type",
geom = "density",
transform_fun = log10)
plot_histogram_mult(df, var = c("critic_score", "year_of_release"))
#> [[1]]
#>
#> [[2]]
K tvorbě boxplotů můžeme použít funkce plot_box()
a
plot_box_mult()
, které mají tyto argumenty:
data
: použitý dataset.var
: zobrazená proměnná (character).groups
: rozdělení do skupin podle jiné proměnné
(character).fill
: nastavení výplňě podle další proměnné
(character).facet
: fazetovat graf podle další
proměnné¨(character).geom
: "boxplot"
pro klasický krabicový
graf, "violin"
pro houslouvý graf.order
: Seřadit “krabice” podle madiánu.plot_box(df, "user_score", groups = "genre")
plot_box_mult(df,
var = c("user_score", "critic_score"),
groups = "genre")
#> [[1]]
#>
#> [[2]]
K tvorbě bodových grafů (scatterplots) můžeme použít funkce
plot_box()
a plot_box_mult()
, které mají tyto
argumenty:
data
: použitý dataset.xvar
: proměnná zobrazená na ose X (character).yvar
: proměnná zobrazená na ose Y (character).color
: nastavení barvy bodů podle další proměnné
(character)geom
: "point"
pro klasický bodový graf,
"jitter"
pro bodový graf s malým hánodným vychýlením bodů a
"count"
pro zobrazení nakupení více případů velikostí
bodu.alpha
: míra neprůhlednosti bodů (od 0 do 1).sample
: nezobrazovat všechny případy, pouze náhodný
vzorek n-případů (integer).fit_line
: zobrazit trend? (logical).method
: funkce pro vytvoření spojnice trendu (např.
“loess” nebo “lm”)plot_scatter(df, xvar = "user_score", yvar = "critic_score",
color = "handheld",
geom = "jitter",
sample = 1000)
plot_scatter_mult(df,
xvar = c("user_score", "user_score"),
yvar = c("critic_score", "log10(global_sales)"),
geom = "jitter", method = "lm",
sample = 1000)
#> [[1]]
#>
#> [[2]]
Mozaikové grafy jsou velmi podobné skládaným sloupcovým grafům, ale
kromě toho informují o zastopení jednotlivých kategorií na ose X
prostřednictvím šířky sloupců. K tvorbě mozaikových grafů můžeme použít
funkce plot_mosaic()
a plot_mosaic_mult()
,
které mají tyto argumenty:
data
: použitý dataset.xvar
: proměnná zobrazená na ose X, o které uvažujeme
jako o “nezávislé” (character).yvar
: proměnná zobrazená na ose Y a pomocí výplně
(character), o které uvažujeme jako o “závislé”.plot_mosaic(df, "genre", "rating")
plot_mosaic(df %>% drop_na(rating),
xvar = "genre", yvar = "rating")
plot_mosaic_mult(df %>% drop_na(rating),
xvar = "platform_type",
yvar = c("genre", "handheld", "rating"))
#> [[1]]
#>
#> [[2]]
#>
#> [[3]]
Tabulky s četnostmi je možné vytvořit s využítím balíčku dplyr, a to s využitím funkce count. Můžeme například chtít zjistit četnosti žánrů v závislosti na dekádě.
# Nejdříve si vypočteme absolutní četnosti
<- df %>%
freq mutate(genre = fct_explicit_na(genre, na_level = "Undetermined"),
decade = fct_explicit_na(decade, na_level = "Not released yet")) %>%
count(decade, genre,
.drop = FALSE)
# Pak dopočteme relativní četnost žánrů v rámci dekády
<- freq %>%
freq group_by(decade) %>%
mutate(p = n/sum(n))
freq
#> # A tibble: 65 × 4
#> # Groups: decade [5]
#> decade genre n p
#> <fct> <fct> <int> <dbl>
#> 1 1980s Action 66 0.322
#> 2 1980s Adventure 2 0.00976
#> 3 1980s Fighting 4 0.0195
#> 4 1980s Misc 8 0.0390
#> 5 1980s Platform 33 0.161
#> 6 1980s Puzzle 19 0.0927
#> 7 1980s Racing 8 0.0390
#> 8 1980s Role-Playing 9 0.0439
#> 9 1980s Shooter 30 0.146
#> 10 1980s Simulation 3 0.0146
#> # … with 55 more rows
# A nakonec můžeme údaj o dekádě, ze které data pocházejí, "rozprostřít"
# do sloupců pomocí pivot_wider()
%>%
freq pivot_wider(names_from = decade,
values_from = c(n, p),
names_vary = "slowest")
#> # A tibble: 13 × 11
#> genre n_1980s p_1980s n_1990s p_1990s n_2000s p_2000s n_2010s p_2010s n_Not…¹
#> <fct> <int> <dbl> <int> <dbl> <int> <dbl> <int> <dbl> <int>
#> 1 Acti… 66 0.322 162 0.0915 1584 0.172 1496 0.283 62
#> 2 Adve… 2 0.00976 97 0.0548 631 0.0686 563 0.107 10
#> 3 Figh… 4 0.0195 193 0.109 441 0.0480 199 0.0377 12
#> 4 Misc 8 0.0390 116 0.0655 1021 0.111 576 0.109 29
#> 5 Plat… 33 0.161 125 0.0706 567 0.0617 153 0.0290 10
#> 6 Puzz… 19 0.0927 71 0.0401 365 0.0397 114 0.0216 11
#> 7 Raci… 8 0.0390 183 0.103 798 0.0868 237 0.0449 23
#> 8 Role… 9 0.0439 172 0.0971 732 0.0796 570 0.108 17
#> 9 Shoo… 30 0.146 137 0.0774 719 0.0782 410 0.0776 27
#> 10 Simu… 3 0.0146 86 0.0486 551 0.0599 218 0.0413 16
#> 11 Spor… 23 0.112 304 0.172 1404 0.153 575 0.109 42
#> 12 Stra… 0 0 123 0.0695 380 0.0413 170 0.0322 10
#> 13 Unde… 0 0 2 0.00113 0 0 0 0 0
#> # … with 1 more variable: `p_Not released yet` <dbl>, and abbreviated variable
#> # name ¹`n_Not released yet`
Na závěr si ukážeme operace, které se budou hodit při práci s psychologickými daty. Ke cvičením použijeme dataset, který obsahuje pouze několik proměnných: id respondenta, jeho pohlaví, věk a odpovědi na otázky Rosenberg self-esteem scale. Níže je import dat a jejich základní přehled.
<- haven::read_sav("https://is.muni.cz/el/fss/podzim2022/PSYn5320/um/datasets/rses_data.sav")
rses glimpse(rses)
#> Rows: 11,089
#> Columns: 13
#> $ id <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, …
#> $ sex <dbl+lbl> NA, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,…
#> $ age <dbl> 99, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17,…
#> $ rses01 <dbl+lbl> 4, 4, 3, 5, 5, 3, 5, 2, 5, 5, 5, 4, 4, 2, 5, 4, 1, 4, 5, 6,…
#> $ rses02 <dbl+lbl> 5, 6, 5, 4, 3, 4, 5, 5, 4, 2, 6, 4, 5, 4, 3, 4, 6, 4, 2, 5,…
#> $ rses03 <dbl+lbl> 2, 5, 3, 5, 4, 4, 5, 4, 5, 6, 5, 4, 4, 4, 5, 5, 5, 4, 4, 5,…
#> $ rses04 <dbl+lbl> 4, 4, 4, 5, 5, 5, 5, 4, 5, 6, 4, 4, 4, 4, 5, 6, 4, 5, 4, 4,…
#> $ rses05 <dbl+lbl> 4, 5, 4, 3, 3, 3, 2, 4, 4, 1, 3, 3, 3, 4, 5, 3, 4, 2, 3, 2,…
#> $ rses06 <dbl+lbl> 4, 6, 4, 3, 2, 3, 2, 2, 3, 1, 5, 4, 5, 4, 3, 4, 4, 4, 3, 3,…
#> $ rses07 <dbl+lbl> 3, 6, 5, 5, 5, 3, 4, 4, 5, 6, 4, 4, 4, 4, 5, 5, 3, 6, 5, 5,…
#> $ rses08 <dbl+lbl> 5, 3, 5, 3, 5, 4, 4, 5, 5, 2, 3, 5, 5, 5, 5, 5, 3, 4, 4, 4,…
#> $ rses09 <dbl+lbl> 2, 5, 5, 3, 4, 3, 2, 2, 3, 2, 5, 5, 5, 4, 4, 4, 3, 2, 3, 3,…
#> $ rses10 <dbl+lbl> 2, 3, 3, 5, 4, 4, 5, 4, 5, 5, 4, 4, 3, 2, 5, 6, 2, 5, 4, 5,…
summary(rses)
#> id sex age rses01
#> Min. : 0.0 Min. :0.000 Min. : 0.00 Min. :1.000
#> 1st Qu.: 22.0 1st Qu.:1.000 1st Qu.:18.00 1st Qu.:2.000
#> Median : 523.5 Median :2.000 Median :20.00 Median :3.000
#> Mean : 145046.4 Mean :1.503 Mean :19.98 Mean :2.774
#> 3rd Qu.: 1790.2 3rd Qu.:2.000 3rd Qu.:22.00 3rd Qu.:3.000
#> Max. :1427587.0 Max. :2.000 Max. :99.00 Max. :6.000
#> NA's :8285 NA's :402 NA's :629 NA's :1703
#> rses02 rses03 rses04 rses05
#> Min. :1.000 Min. :1.000 Min. :1.000 Min. :1.000
#> 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000
#> Median :2.000 Median :3.000 Median :3.000 Median :2.000
#> Mean :2.485 Mean :2.864 Mean :2.904 Mean :2.466
#> 3rd Qu.:3.000 3rd Qu.:4.000 3rd Qu.:4.000 3rd Qu.:3.000
#> Max. :6.000 Max. :6.000 Max. :6.000 Max. :6.000
#> NA's :1721 NA's :2480 NA's :1714 NA's :1737
#> rses06 rses07 rses08 rses09
#> Min. :1.000 Min. :1.000 Min. :1.000 Min. :1.000
#> 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:2.000 1st Qu.:1.000
#> Median :2.000 Median :3.000 Median :3.000 Median :3.000
#> Mean :2.408 Mean :2.904 Mean :2.682 Mean :2.493
#> 3rd Qu.:3.000 3rd Qu.:4.000 3rd Qu.:4.000 3rd Qu.:3.000
#> Max. :6.000 Max. :6.000 Max. :6.000 Max. :6.000
#> NA's :2160 NA's :1722 NA's :2487 NA's :2474
#> rses10
#> Min. :1.000
#> 1st Qu.:2.000
#> Median :3.000
#> Mean :2.762
#> 3rd Qu.:4.000
#> Max. :6.000
#> NA's :2475
Pokud pomocí balíčku haven importujeme
dataset z SPSS, můžeme si pomocí funkce metadata()
nechat
zobrazit metadata z SPSS: kromě názvů proměnných tedy i jejich popisky a
popisky hodnot
<- metadata(rses)
rses_md rses_md
#> # A tibble: 13 × 3
#> var_names var_labels value…¹
#> <chr> <chr> <chr>
#> 1 id "respondent's ID" <NA>
#> 2 sex "respondent's sex" 1 = ma…
#> 3 age "Respondent's age in years" <NA>
#> 4 rses01 "On the whole, I am satisfied with myself" 1 = st…
#> 5 rses02 "At times I think I am no good at all." 1 = st…
#> 6 rses03 "I feel that I have a number of good qualities." 1 = st…
#> 7 rses04 "I am able to do things as well as most other people. \r" 1 = st…
#> 8 rses05 "I feel I do not have much to be proud of." 1 = st…
#> 9 rses06 "I certainly feel useless at times." 1 = st…
#> 10 rses07 "I feel that I'm a person of worth, at least on an equal p… 1 = st…
#> 11 rses08 "I wish I could have more respect for myself. \r" 1 = st…
#> 12 rses09 "All in all, I am inclined to feel that I am a failure." 1 = st…
#> 13 rses10 "I take a positive attitude toward myself." 1 = st…
#> # … with abbreviated variable name ¹value_labels
První věc, kterou můžeme udělat, je podívat se na chybějící data.
Kdybychom chtěli vypočíst počet nebo podíl chybějících nebo naopak
validních hodnot pro každý řádek/případ ve specifikovaných sloupcích,
můžeme použít tyto funkce v rámci mutate()
. Stačí v nich
pouze zadat vybrané sloupce (pokud všechny, můžeme použít
èverything()
):
row_missing_n()
: počet chybějících hodnot.row_missing_p()
: podíl chybějících hodnot.row_valid_n()
: počet validních (nechybějících)
hodnot.row_valid_p()
: podíl validních (nechybějících)
hodnot.<- rses %>%
rses mutate(
n_miss_all = row_missing_n(everything()),
)
%>%
rses filter(n_miss_all == 13)
#> # A tibble: 351 × 14
#> id sex age rses01 rses02 rses03 rses04 rses05 rses06 rses07 rses08
#> <dbl> <dbl+lbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+> <dbl+> <dbl+> <dbl+> <dbl+>
#> 1 NA NA NA NA NA NA NA NA NA NA NA
#> 2 NA NA NA NA NA NA NA NA NA NA NA
#> 3 NA NA NA NA NA NA NA NA NA NA NA
#> 4 NA NA NA NA NA NA NA NA NA NA NA
#> 5 NA NA NA NA NA NA NA NA NA NA NA
#> 6 NA NA NA NA NA NA NA NA NA NA NA
#> 7 NA NA NA NA NA NA NA NA NA NA NA
#> 8 NA NA NA NA NA NA NA NA NA NA NA
#> 9 NA NA NA NA NA NA NA NA NA NA NA
#> 10 NA NA NA NA NA NA NA NA NA NA NA
#> # … with 341 more rows, and 3 more variables: rses09 <dbl+lbl>,
#> # rses10 <dbl+lbl>, n_miss_all <dbl>
Vypadá to, že některé řádky/případy jsou prázdné nebo téměř úplně prázdné a ani nemají ID. Tyto řádky asi nemá smysl v datasetu ponechávat, takže je s klidným svědomím můžeme odstranit.
<- rses %>%
rses filter(n_miss_all < 13)
Další věc, kterou můžeme udělat, je převést pohlaví na faktor,
protože defaultně balíček haven importoje
kategorické proměnné jako vektory typu double, které ale mají uložné
labely atributech. K tomu balíček haven nabízí funkci
as_factor
.
<- rses %>%
rses mutate(sex = as_factor(sex))
Lepší je ale ověřit, zda jsou všechny úrovně správně definovány,
takže se podíváme na četnosti pomocí funkce count()
:
%>%
rses count(sex)
#> # A tibble: 4 × 2
#> sex n
#> <fct> <int>
#> 1 0 2
#> 2 male 5303
#> 3 female 5382
#> 4 <NA> 51
Jak vidíme, v datech se kromě hodnot male
,
female
a NA
vyskytly i hodnoty 0
.
Protože nevíme, co tyto hodnoty znamenají a jsou jen dvě, má asi
největší smysl zacházet s nimi jako s missing values, tudíž je také
převést na NA
. K tomu má balíček
forcats funkci fct_recode()
. Ta
má tuto obecnou podobu, kde x
je modifikovaný faktor:
fct_recode(x,
"nový_label_1" = "starý_label_1",
"nový_label_2" = "starý_label_2",
NULL = "úroveň_která_bude_NA")
<- rses %>%
rses mutate(sex = fct_recode(sex,
"Muži" = "male",
"Ženy" = "female",
NULL = "0"))
count(rses, sex)
#> # A tibble: 3 × 2
#> sex n
#> <fct> <int>
#> 1 Muži 5303
#> 2 Ženy 5382
#> 3 <NA> 53
levels(rses$sex)
#> [1] "Muži" "Ženy"
Kdybychom chtěli s chybějícími hodnotami pracovat jako se svébytnou
úrovní dané proměnné, je vhodné ji přidělit explicitní název pomocí
funkce fct_explicit_na()
:
<- rses %>%
rses mutate(sex = fct_explicit_na(sex, na_level = "(missing)"))
count(rses, sex)
#> # A tibble: 3 × 2
#> sex n
#> <fct> <int>
#> 1 Muži 5303
#> 2 Ženy 5382
#> 3 (missing) 53
Dále se podíváem na proměnnou věk, jestli se v ní nevyskytují nějaké zjevně neplatné hodnoty. Vytvoříme tedy jednoduchý histogram věku.
# Histogram věku (age)
ggplot(rses, aes(age)) +
geom_histogram() +
scale_x_continuous(breaks = seq(0, 100, by = 5))
Vypadá to, že ano. Blíže se tedy zaměříme na věk mimo rozmezí 10–50 let.
# Pozor na to, že před between() je výkřičník kvůli negaci
%>%
rses filter(!between(age, 10, 50))
#> # A tibble: 11 × 14
#> id sex age rses01 rses02 rses03 rses04 rses05 rses06
#> <dbl> <fct> <dbl> <dbl+lb> <dbl+lb> <dbl+lb> <dbl+lb> <dbl+lb> <dbl+lb>
#> 1 1 e+ 0 (missi… 99 4 [rat… 5 [agr… 2 [dis… 4 [rat… 4 [rat… 4 [rat…
#> 2 4.24e+ 2 Muži 99 5 [agr… 5 [agr… 4 [rat… 4 [rat… NA 4 [rat…
#> 3 5.1 e+ 2 Muži 99 4 [rat… 4 [rat… 3 [rat… 4 [rat… 3 [rat… 3 [rat…
#> 4 5.56e+ 2 (missi… 99 3 [rat… 5 [agr… 4 [rat… 5 [agr… 4 [rat… 4 [rat…
#> 5 1.2 e-12 Muži 0 4 [rat… 1 [str… NA 4 [rat… 1 [str… 4 [rat…
#> 6 NA Ženy 0 4 [rat… 1 [str… NA 4 [rat… 4 [rat… 4 [rat…
#> 7 NA Ženy 0 4 [rat… 2 [dis… NA 3 [rat… 2 [dis… 2 [dis…
#> 8 NA Muži 2 2 [dis… 4 [rat… 3 [rat… 3 [rat… 2 [dis… 2 [dis…
#> 9 NA Muži 59 NA NA NA NA NA NA
#> 10 NA Ženy 62 NA NA NA NA NA NA
#> 11 NA Ženy 54 2 [dis… 3 [rat… 2 [dis… 1 [str… 3 [rat… 2 [dis…
#> # … with 5 more variables: rses07 <dbl+lbl>, rses08 <dbl+lbl>,
#> # rses09 <dbl+lbl>, rses10 <dbl+lbl>, n_miss_all <dbl>
Vypadá to, že hodnoty okolo 60 let jsou ještě uvěřitelné, ale hodnoty
0, 2 a 99 nikoli, konvertujeme je tedy na NA
. Existuje
několi možných způsobů, jak to udělat. Můžete si vybrat kterýkoli z
nich:
# Pomocí mutate() a ifelse()
<- rses %>%
rses mutate(age = ifelse(age %in% c(0, 2, 99), # podmínka
NA, # if TRUE
# if FALSE
age))
# Subseting a assignment
$age[rses$age %in% c(0, 2, 99)] <- NA rses
Výsledek můžeme znovu zkontrolovat pomocí histogramu, ale můžeme si také zobrazit četnost (po zaokrouhlení věku na celá čísla):
%>%
rses count(age = round(age, digits = 0)) %>%
mutate(percent = n/sum(n)*100) %>%
print(n = Inf)
#> # A tibble: 42 × 3
#> age n percent
#> <dbl> <int> <dbl>
#> 1 12 279 2.60
#> 2 13 156 1.45
#> 3 14 6 0.0559
#> 4 15 3 0.0279
#> 5 16 407 3.79
#> 6 17 1013 9.43
#> 7 18 1371 12.8
#> 8 19 1794 16.7
#> 9 20 1486 13.8
#> 10 21 1176 11.0
#> 11 22 1071 9.97
#> 12 23 756 7.04
#> 13 24 356 3.32
#> 14 25 212 1.97
#> 15 26 97 0.903
#> 16 27 48 0.447
#> 17 28 41 0.382
#> 18 29 27 0.251
#> 19 30 22 0.205
#> 20 31 19 0.177
#> 21 32 13 0.121
#> 22 33 11 0.102
#> 23 34 15 0.140
#> 24 35 7 0.0652
#> 25 36 8 0.0745
#> 26 37 9 0.0838
#> 27 38 5 0.0466
#> 28 39 3 0.0279
#> 29 40 5 0.0466
#> 30 41 5 0.0466
#> 31 42 9 0.0838
#> 32 43 4 0.0373
#> 33 44 1 0.00931
#> 34 45 5 0.0466
#> 35 46 3 0.0279
#> 36 47 3 0.0279
#> 37 49 1 0.00931
#> 38 50 2 0.0186
#> 39 54 1 0.00931
#> 40 59 1 0.00931
#> 41 62 1 0.00931
#> 42 NA 286 2.66
Někdy také může mít smysl nějakou proměnnou diskrtizovat. Ukážeme si
to znovu na věku. Vytvoříme si novou proměnnou age_cat
,
která bude vyjadřovat různé “věkové kategorie”. K tomu použijeme funkci
cut()
, která má tyto hlavní argumenty:
x
: vektor, který chceme diskretizovat.breaks
: předěly mezi jednotlivými intervaly včetně
konců v podobě číselného věktoru.labels
: labely pro jednotlivé úrovně.right
: zda mají být intervaly zprava uzavřené a zleva
otevřené (righ = TRUE
), nebo naopak zprava otevřené a zleva
uzavřené (righ = FALSE
).include.lowest
: zda do intervalu zahrnout i úplně první
hodnotu v breaks
(je-li right = TRUE
), resp.
úplně poslední hodnotu breaks
(je-li
right = FALSE
).Zkusíme si vytvořit zprava otevřené, zleva uzavřené intervaly, a to od 10 let v šířce 5 let, ale poslední interval bude širší a bude zahrnovat osoby mající 30 či více let. Pro upřesnění, když je interval uzavřený, znamená to, že danou krajní hodnotu ještě zahrnuje, když je otevřený, znamená to, že danou krajní hodnotu už nezahrnuje.
<- rses%>%
rses mutate(
age_cat= cut(age,
breaks = c(10, 15, 20, 25, 30, Inf),
labels = c("10–14.9", "15–19.9", "20–24.9", "25–29.9", "30+"),
right = FALSE,
include.lowest = TRUE)
)
%>%
rses ggplot(aes(age, age_cat)) +
geom_boxplot()
Aby se nám dále s položkami RSES lépe pracovalo, vytvoříme si dva
vektory: items_all
(s názvy všech položek) a
items_reversed
(pouze s názvy reverzních položek). K tomu
použijeme funkci item_range()
, která má tyto argumenty
(pouze prefix
a range
jsou povinné):
prefix
: předpona položek, např. “rses”.range``: číselné rozmezí položek (např. číselný vektor
1:10`).suffix
: volitelná přípona položek (není nutné
specifikovat).width
: konstantní šířka číselného rozmezí položek. Na
začátek čísel budou doplněny nuly, ať se dosáhne zadané šířky. Například
pokud bychom nastavili width = 3
a použili
range = 1:3
, generovalo by se 001
,
002
, 003
.with.suffix
: přidat příponu jen některým položkám
(číslený vektor)Oba vektory bychom vytvořili takto:
<- item_range("rses", range = 1:10, width = 2)
items_all items_all
#> [1] "rses01" "rses02" "rses03" "rses04" "rses05" "rses06" "rses07" "rses08"
#> [9] "rses09" "rses10"
# Položky 2, 5, 6, 8 a 9 jsou reverzní
<- item_range("rses", range = c(2, 5, 6, 8, 9), width = 2)
items_reversed items_reversed
#> [1] "rses02" "rses05" "rses06" "rses08" "rses09"
Kdybychom pak chtěli rekódovat opačně skórované položky a vytvořit nový dataframe s rekódovanými položkami, např. `rses_rec``, mohlo by nás napadnout ručně specifikovat každé jednotlivé rekódování:
<- rses %>%
rses_rec mutate(
rses02 = 7 - rses02,
rses05 = 7 - rses05,
rses06 = 7 - rses06,
rses08 = 7 - rses08,
rses09 = 7 - rses09
)
To je ale poměrně neefektivní, hlavně když máme mnoho škál a hodně
položek a navíc přitom hrozí, že uděláme nějakou chybu. Místo toho
můžeme využít toho, že máme připravený vektor s položkami a použít
funkci reverse_score()
v rámci across()
.
Pomocí across()
můžeme totiž aplikovat tutéž funkci na
několik sloupců najednou. Výběr můžeme provést stejně jako v rámci
select()
. Když máme textový vektor s položkami, použijeme
all_of(items_reversed)
pro výběr transformovaných sloupců.
Pak uvedeme funkci, kterou chceme použít, na všechny vybrané sloupce, a
to reverse_score()
. Nakonec jen uvedeme dotatečné argumenty
pro funkci reverse_score, a to min
a max
,
kterými bychom měli specifikovat minimální a maximální hodnotu škály
(zde bylo rozmezí 1–6 od silně nesouhlasím po silně souhlasím, proto
min = 1
a max = 6
).
<- rses %>%
rses_rec mutate(
across(all_of(items_reversed), reverse_score, min = 1, max = 6)
)
Když máme položky rekódovány, můžeme vypočíst celkový skór jako
průměr položek pomocí funkce row_mean()
. Vybrat sloupce v
ní můžeme stejně jako ve funkci select()
a pak argumentem
min.valid
můžeme specifikovat, kolik minimálně platných
hodnot musí být na řádku ve vybranýých sloupcích (proměnných), aby se
celkový skór vypočelt (pokud je počet platných hodnot menší než
min.valid
, vrátí nám to pro daný řádek/respondenta
NA
).
<- rses_rec %>%
rses_rec mutate(
rses_total = row_mean(all_of(items_all), min.valid = 5)
)
Nakonec se můžeme pomocí boxplotu podívat, jak vypadá rozdělení
rses_total
v závislosti na pohlaví a věkové kategorii.
%>%
rses_rec drop_na(age_cat, sex) %>%
ggplot(aes(age_cat, rses_total, color = sex)) +
geom_boxplot()