R a práce s geodaty
Již umíme data upravit v externím programu a načíst do prostředí R a umíme s daty provádět základní operace. V rámci tohoto cvičení si vyzkoušíme další možné operace s daty, práci s podvýběry, spojování datových matic a další potřebné funkce pro operaci s daty. V druhé části si ukážeme základní postupy pro vytváření grafů.
Práce s datovou maticí v R
Při práci s datovou maticí často nastává okamžik, kdy chcete pracovat pouze s podmnožinou dat, odstranit část dat splňující určitou podmínku nebo se různě seřadit. Řada z těchto operací lze provést relativně jednoduše v externím programu (např. MS Excel) a následně takto upravená data importovat do R. Nicméně často je potřeba tyto výběry dělat častěji a tak je zdlouhavé a nepraktické používat k tomu další program a vytvářet mnoho různých verzí dat. Proto je určitá znalost těchto metod potřebná. V minulém cvičení jsme si představili funkci read.table, která importuje data jako datový rámec (data frame), což je výhodné, protože celá řada funkcí pracuje právě s datovým rámcem. Pokud nepracujete v RStudiu, ale přímo v konzole, ale i v RStudiu může být potřebná funkce names(), která vrací názvy všech sloupců v datovém rámci. Tento příkaz se doporučuje dělat ihned po importu a to spolu s funkcí str() (structure), která sumarizuje základní informace o všech proměnných v datovém souboru.
V tomto cvičení budeme pracovat s daty o průměrných a mediánových mzdách v krajích ČR za dva různé roky (data ke stažení níže). Po načtení dat zobrazte názvy a strukturu dat. Tento postup ověří, zda jsou data korektně načtená a zda datové typy jednotlivých atributů odpovídají vašim požadavkům.
> names(dPlaty)
Z výsledku je patrné, že datový rámec obsahuje 6 proměnných, kdy první sloupec je prázdný, druhý (název kraje) obsahuje tzv. factor, což je kategoriální proměnná, zbývající 4 (průměrná mzda, medián mzdy, rok a pohlaví, kdy 1=muž, 2=žena, 3=celkem) jsou pak numerické. Vše je importováno správně.
V R existují tři základní možnosti, jak pracovat s proměnnými z datového rámce. První z nich je zápis (data=nazev_data_frame), který je sice často doporučován, ale řadou funkcí není podporován. Obecně platí, že pokud je funkcí podporován, měl by být použit. Např. níže uvedený kód vytvoří boxploty mediánu mezd pro jednotlivé kraje s využitím data=.
boxplot(M_MZDA ~ factor(KRAJ), data=dPlaty)
Druhým přístupem je použití symbolu $, který jsme již používali v minulých cvičeních. Pro zobrazení hodnot průměrné mzdy stačí zapsat dPlaty$P_MZDA a celý vektor je vypsán. Poslední možností je zápis s využitím hranatých závorek, pro zobrazení stejného sloupce pak zápis vypadá takto dPlaty[,3], jelikož sloupec s průměrnou mzdou je třetí v pořadí (používáme hodnotu za čárkou, protože pracujeme se sloupcem). Je možné zápis upravit takto dPlaty[,”P_MZDA”]. V doporučené literatuře je preferován zápis s využitím $, i když je dobré znát všechny typy.
Při práci s datovým rámcem a celou řadou funkcí se opakované zapisování názvu datového rámce stává velice nepříjemné. Stále stejný zápis je možné nahradit funkcí attach(), kterou řekneme, že od daného okamžiku budou všechny proměnné brány jen z daného datového rámce. Pro náš případ tedy stačí zapsat attach(dPlaty) a pak zavolat vybranou proměnnou a vypočítat z ní směrodatnou odchylku sd(M_MZDA). Tato funkce má však i svá úskalí a to pokud jsou názvy proměnné použity jak v daném datovém rámci, tak také jinde nebo pokud názvy proměnných odpovídají názvu některé funkce použité v R. V případě českých názvů však toto nehrozí. Po skončení práce s daným datovým rámcem se doporučuje toto napojení deaktivovat a to příkazem detach(). Pokud však pracujete s jedním datovým rámcem a proměnné jsou správně pojmenovány, tak se není čeho obávat a tato funkce ulehčí značně práci.
Podmíněný výběr
V příkladu výše jsme vypočítali směrodatnou odchylku pro všechny mediány mezd – ve všech krajích, v ČR, pro obě pohlaví, pro populaci celkem a pro dva různé roky. Je jasné, že toto číslo je nepoužitelné. Jak tedy postupovat, pokud chceme pracovat pouze s částí dat, např. rokem 2012 nebo ještě komplikovaněji, chceme pracovat jen s kraji, rokem 2012 a s ženami. V prvním kroku je dobré si vypsat všechny unikátní hodnoty pro daný sloupec, řekněme, že chceme pracovat jen s rokem 2012. Vypíšeme si jedinečné hodnoty sloupce ROK a to příkazem unique(dPlaty$ROK) a zjistíme, že jsou zde hodnoty 2010 a 2012. Pro výběr dat za rok 2012 postupujeme takto
Vyber<-dPlaty$ROK == 2012 # vytvoří Boolean vektor o velikosti počtu záznamů s rokem = 2012 (True)
dPlaty2012<-dPlaty[Vyber,] # přiřadí hodnoty TRUE do proměnné dPlaty2012 (pracujeme s řádky, proto zápis před čárkou)
dPlaty2012 # zobrazí data pro rok 2012
Pokud chceme vytvořit komplikovanější podmíněný výběr, není to nic komplikovaného. Oproti předchozímu zápisu jsme vše zapsali v jednom řádku a použili logický operátor and.
dPlatyC_2012 <- dPlaty[dPlaty$POHLAVI==3 & dPlaty$ROK==2012,]
pokud chci muže i ženy, pak můžeme zapsat
dPlatyMZ_2012 <- dPlaty[(dPlaty$POHLAVI==1 | dPlaty$POHLAVI==2) & dPlaty$ROK==2012,] nebo
dPlatyMZ_2012 <- dPlaty[dPlaty$POHLAVI!=3 & dPlaty$ROK==2012,]
Data může být dobré také vhodně seřadit, např. při vizuální kontrole apod. K seřazení od nejmenší k největší hodnotě je možné použít tento zápis (pro opačné řazení je potřeba změnit argument decreasing na TRUE).
seraz <- order(dPlatyC_2012$P_MZDA, decreasing = FALSE)
> dPlatyC_2012[seraz,]
Propojení dvou datových matic přes společný atribut
Netřeba vysvětlovat, k čemu je tento postup vhodný. Ukážeme si ho na příkladu, kdy k naší současné tabulce o mzdách v krajích chceme připojit druhou tabulku s počtem obyvatel dle věku v krajích. Naším cílem je vypočítat celkovou vydělanou mzdu za předpokladu že všichni obyvatelé ve věku 15-64 jsou zaměstnaní a pobírají medián mzdy (nesmyslný předpoklad). Tabulka s demografickými daty se nazývá DEMOGRAFIE_KRAJE.
# provedeme import tabulky do R
excelLink2 <- odbcConnectExcel2007(“DEMOGRAFIE_KRAJE.xlsx”)
dDemog <- sqlFetch(excelLink2, “List1”)
# vybereme jen záznamy pro ženy v roce 2012
dDemog_Z_2012 <- dDemog[dDemog$POHLAVI==”ženy” & dDemog$ROK==2012, ]
# napojíme k datům s platy, které jsou rovněž pro ženy a rok 2012
dSpoj_Z_2012 <- merge(dPlatyZ_2012, dDemog_Z_2012, by=”KRAJ”)
# vypočítáme novou proměnnou = počet obyvate 15-64 * medián platu
dSpoj_Z_2012 <- transform(dSpoj_Z_2012, castka=VEK_15_64*M_MZDA)
Funkce merge() má celou řadu potřebných parametrů. Pokud se sloupce v obou tabulkách nejmenují stejně, je možné je definovat přesněji by.x = “nazev” a by.y = “nazev”. Dalším vhodným parametrem je all. Standardně je nastaven na FALSE a tak výsledkem jsou skutečně jen propojené řádky. V případě, že k některému řádku není co připojit, tento je odstraněn. Pokud nastavíme hodnotu na TRUE, pak se k tomuto řádku přidají hodnoty NA.
Funkce pro hromadné zpracování
V případě, že dalším cílem naší analýzy by bylo vypočítat aritmetický průměr mediánu mzdy v ČR v 2010 a 2012, tak by byl postup asi značně náročný. Museli bychom data rozdělit podle let a vypočítat průměr zvlášť. Značně rychleji mohu totéž provést s využitím funkce tapply(). Ta umožňuje vypočítat charakteristiky kvantitativní proměnné podmíněné hodnotou kvalitativního znaku. Charakteristiky mohou být průměr mean, medián median, směrodatná odchylka sd, minimum min, maximum max, rozptyl var, sočet hodnot sum, setřídění sort a další funkce.
prPlatMZ_2012 <- tapply(dPlatyMZ_2012$M_MZDA, dPlatyMZ_2012$POHLAVI, mean)
Můžeme také vypočítat charakteristiku pro kvantitativního znaku v závislosti na dvou (a více) proměnných. V příkladu níže je vypočten průměr z průměrných mezd pro každý rok a pohlaví.
tapply(dPlaty$P_MZDA, list(rok=dPlaty$ROK, pohlaví=dPlaty$POHLAVI), mean)
pohlaví
rok 1 2 3
2010 28283.57 21379.57 25279.29
2012 27272.29 21389.50 24625.43
Podobně se dá použít také funkce aggregate()
aggregate(dPlaty$P_MZDA, list(rok=dPlaty$ROK, pohlaví=dPlaty$POHLAVI), FUN= mean)
Funkce tapply() počítá vybraný ukazatel pro části záznamů jedné vybrané proměnné. Pokud však chci počítat průměry pro všechny záznamy a několik proměnných musím použít buďto po sobě několik funkcí mean() nebo si pomoci funkcí sapply() nebo lapply(). Rozdíl mezi těmito funkcemi je výsledný formát. Zatímco výsledkem sapply() je vektor, tak výsledkem lapply() je list.
Chci tedy vypočítat z naší spojené tabulky (ženy v 2012) směrodatné odchylky pro sloupce P_MZDA, M_MZDA, POPULACE a VEK15_64 (sloupce 3-8)
sapply(dSpoj_Z_2012[,3:8], FUN=sd)
P_MZDA M_MZDA ROK.x POHLAVI.x POPULACE VEK_0_14
2549.042 1925.417 0.000 0.000 172735.493 24643.413
Tabulka četností
V tabulce je možné zobrazit absolutní či relativní četnosti hodnot v tabulce. Pro absolutní četnosti je funkce table() a pro relativní hodnoty pak funkce prop.table(). V našem příkladě jsou výsledné hodnoty stejné.
tabulka=table(dPlaty$KRAJ, dPlaty$POHLAVI)
prop.table(tabulka)
Tvorba grafů a diagramů
Grafy a diagramy se využívají ať už pro explorační analýzu tak i pro finální vizualizaci hodnot. V této části si ukážeme jak vytvořit nejběžnější typy diagramů a grafů (budeme oba typy nazývat grafy). U většiny grafů si ukážeme jen základní nastavení a u jednoho si graf dotvoříme k dokonalosti. R je pozitivně hodnocen pro jeho kvalitní tvorbu grafů, jsme schopni udělat nejrůznější alternativy a navíc grafy nebudou “excel looking”, což vždy potěší.
Bodový graf
Základní funkcí pro vykreslování závislosti dvou proměnných je plot(), kdy se jako argumenty zapisuje proměnná vykreslená na ose x a pak proměnná pro osu y.
plot(dPlatyZ_2012$P_MZDA, dPlatyZ_2012$M_MZDA) # závislost dvou proměnných
plot(dPlatyZ_2012$P_MZDA, dPlatyZ_2012$M_MZDA, xlab=”Průměrná mzda v roce 2012″, ylab=”Medián mzdy v roce 2012″, xlim=c(19000,30000), ylim=c(17000,26000)) # přidává popisky os a rozsah os
plot(dPlatyZ_2012$P_MZDA, dPlatyZ_2012$M_MZDA, xlab=”Průměrná mzda v roce 2012″, ylab=”Medián mzdy v roce 2012″, xlim=c(min(dPlatyZ_2012$P_MZDA), max(dPlatyZ_2012$P_MZDA)), ylim=c(min(dPlatyZ_2012$M_MZDA), max(dPlatyZ_2012$M_MZDA))) # ekvivalent předešlého zápisu, jen rozsahy jsou brány přímo z dat
V grafu se mohou měnit použité symboly, barvy a velikosti symbolů. Pro změnu typu symbolu se používá parametr pch, kdy standardně je rovna 1. Můžeme však vybírat z 25 různých typů symbolů.
Níže uvedený kód zobrazuje oproti předchozímu navíc rozdělení dle pohlaví, tedy využíváme faktu, že muž je definován 1 a žena 2 a tyto hodnoty vstupují přímo pro výběr daného symbolu. Tedy muži jsou zobrazeny prázdným kolečkem a ženy prázdným trojúhelníkem. Tento postup pochopitelně není možné použít v případě, kdy mám kvalitativní informaci zapsanou textem. V tomto případě musíme nejdříve texty překódovat na číselné kódy.
plot(dPlatyMZ_2012$P_MZDA, dPlatyMZ_2012$M_MZDA, xlab=”Průměrná mzda v roce 2012″, ylab=”Medián mzdy v roce 2012″, xlim=c(min(dPlatyMZ_2012$P_MZDA), max(dPlatyMZ_2012$P_MZDA)), ylim=c(min(dPlatyMZ_2012$M_MZDA), max(dPlatyMZ_2012$M_MZDA)), main= “Závislost průměrného a mediánového platu v krajích ČR dle pohlaví”, pch=dPlatyMZ_2012$POHLAVI)
Histogram a hustotní graf
Pro histogram existuje funkce hist(x), kde x je vektor hodnot pro vykreslení. Atributem je freq=FALSE, který zobrazuje pravděpodobnost místo četností. Atribut breaks= nastavuje počet intervalů.
hist(dPlatyMZ_2012$P_MZDA, breaks=7, col=”red”, main=”Průměrná mzda”, xlab=”Průměrná mzda”)
Jak jistě víte, histogram není úplně nejlepší pro zobrazení tvaru distribuce, protože je silně závislý na počtu intervalů, který použijeme. Proto se častěji používá křivka hustotní funkce a ta se vytváří pomocí funkce plot(density(x)).
plot(density(dPlatyMZ_2012$P_MZDA), main=”Průměrná mzda”)
Sloupcový graf
Ten se vytváří s použitím funkce barplot(), kdy parametrem je vektor nebo matice. Pokud je vstupem vektor, pak velikost každého sloupce odpovídá hodnotě ve vektoru. Pokud vstupuje matice a parametr beside=FALSE, pak každý sloupec odpovídá hodnotě parametru v rámci dané proměnné. Pokud beside=TRUE, pak se jedná o skládaný graf. Argument names.arg (textový vektor) se používá pro popis sloupců a parametr horiz=TRUE vytvoří horizontální sloupce.
barplot(dPlatyZ_2012$P_MZDA, main=”Průměrná mzda”, xlab=”Průměrná mzda”)
Výsečový graf
Výsečový graf se vytváří funkcí pie(). Vstupem je vektor nezáporných hodnot a všechny ostatní argumenty jsou dobrovolné. Mezi často používané argumenty patří labels, který přidává popisky jednotlivých výsečí, main pro přidání názvu, col pro volbu barev. Může být zvolena některá z palet, případně může být vytvořena vlastní paleta, např. col = c(“purple”, “violetred1”, “green3”, “cornsilk”, “cyan”, “white”)). Dalším z argumentů je clockwise, jelikož výsečový graf je standardně vytvářen proti směru hodinových ručiček, což je silně netradiční. Z tohoto důvodu se doporučuje nastavit hodnotu na TRUE.
pie(dataPie$POPULACE, labels=dataPie$KRAJ, main=”Počet mužů v krajích v roce 2012″, col=rainbow(14), clockwise=TRUE)
I přes všechna negativa existuje také možnost pro vytvoření 3D verze výsečového diagramu. Funkce se nazývá pie3D() a je součástí balíčku plotrix. V níže uvedeném příkazu jsou další argumenty jako labelcex, který zmenší standardní velikost fontu použitého pro popisky a explode, který od sebe odsadí jednotlivé výseče.
pie3D(dataPie$PRUM_VEK, labels=dataPie$KRAJ, main=”Výsečový diagram pro index stáří”, col=rainbow(14), labelcex=0.6, explode=0.1)
Zadání
- data pro samostatnou práci si nalezněte sami na stránce Českého statistického úřadu či jiné instituce. Data musí obsahovat kvantitativní a několik kvalitativních proměnných. Inspirujte se daty pro vedenou část, ve kterých jsou tři kvalitativní a šest kvantitativních proměnných. K této tabulce si najděte ještě jednu. Obě tabulky v dalších krocích propojíte.
- vypočtěte průměr ze sloupce P_MZDA ze všech záznamů s využitím $ a ze sloupce M_MZDA s využitím []
- připojte k datům externí tabulku, kterou si opět naleznete sami
- proveďte komplikovanější podmíněný výběr a vypočtěte rozdíly či jiné proměnné, které v případě vašich dat dávají smysl. Výsledky v rychlosti okomentujte.
- vytvořte z vybraných ukazatelů bodový, sloupcový, výsečový a hustotní graf
Cvičení je vytvořeno v rámci projektu Inovace bakalářských a magisterských studijních oborů na Hornicko-geologické fakultě VŠB-TUO pod číslem CZ.1.07/2.2.00/28.0308. Tento projekt je realizován za spoluúčasti EU.