User Tools

Site Tools


Sidebar

Vít Syrovátka

Úvod do R


Teorie

Sekce Teorie je (a asi ještě dlouho bude) v průběžné výstavbě.

Software

Objekty v R

Cvičení

Data

Zápočet

Další zdroje

R for Data Science (2017) - excelentní tutorial Hadleyho Wickhama následující filozofii tidyversu
Data Processing with dplyr & tidyr - tutorial na úpravu dataframů pomocí tidyversových balíků dplyr a tidyr

r_intro:cs:theory:factor

droplevels()

Faktory

V terminologii R je faktor (anglicky factor) kategoriální proměnná. Kategorie faktoru jsou pak nazývány úrovně (levels). Například pro odlišení pohlaví ptáků bychom použili faktor o dvou úrovních: samec a samice. Dalším příkladem může být typ stanoviště při snímkování vegetace: louka, les, mokřad, ruderál. Jistě vás napadne, proč bychom nemohli použít textový (character) vektor. Abychom pochopili, jaké výhody faktor má, podíváme se na jeho strukturu.

Struktura faktoru

Faktor je vektor celých čísel, která odkazují na jména úrovní. Například u faktoru sex jsou kategoriím female a male přiřazena celá čísla od 1 podle abecedy, tedy female bude mít jedničku a male dvojku. Tyto jedničky a dvojky v proměnné sex nahradí původní female a male a vedle je zapsaná informace, že 1 znamená female a 2 male. To je faktor. Struktura str() faktoru sex s 8 hodnotami, jak nám ji vrátí R vypadá následovně:

Factor w/ 2 levels "female","male": 2 1 1 2 2 1 2 1

R říká, že je to faktor se dvěma úrovněmi “female” a “male” a hodnoty faktoru jsou 2, 1, 1, 2, 2… Na první pozici je tedy “male” (dvojka odkazuje na druhou úroveň, což je male), pak dvakrát “female” (dvě jedničky), pak dvakrát “male”, atd.

Výhody faktoru

První výhodou faktoru je, že zabírá v paměti počítače méně místa než obdobný textový vektor. Jména úrovní složená z mnoha znaků jsou vyjmenována jen jednou, pak už se jen opakují pořadí úrovní.

Pokud chceme změnit názvy kategorií, stačí změnit jména úrovní, samotný numerický vektor zůstane nezměněný.

Nakonec to nejdůležitější. Můžeme s ním počítat všemožné analýzy, ve kterých vystupují kategoriální proměnné, např. ANOVA. A protože faktor je vlastně numerický vektor, můžeme ho použít pro definování typu symbolů a barev v grafech, pro tvorbu krabicových grafů (box-plotů) a pro všelijaké další kejkle.

Vytvoření faktoru z kategoriální proměnné

Z kategoriální proměnné, která je ve formě textového, numerického, nebo logického vektoru vytvoříme faktor snadno pomocí funkce factor().

# nejprve vytvořím vzorový textový vektor:
sex<- c('male','female','female','male','male','female','male','female'
sex
[1] "male"   "female" "female" "male"   "male"   "female" "male"   "female"
 
# Z něj uděláme faktor:
sexF<- factor(sex)
sexF
[1] male   female female male   male   female male   female
Levels: female male

Všimněte si rozdílů mezi faktorem sexF a textovým vektorem sex:

  • na rozdíl od textového vektoru nejsou hodnoty faktoru v uvozovkách,
  • při vypsání faktoru poslední řádek informuje o úrovních (levels) faktoru (u textového vektoru nic takového není).

Pořadí úrovní je dáno abecedním pořadím a je reflektováno v numerických hodnotách faktoru, které na toto pořadí odkazují. Pokud nejsme s abecedním pořadím spokojeni, můžeme ho změnit (viz dále).

Pozor! Při načítání dat a při tvorbě dataframů jsou textové proměnné automaticky převedeny na faktory. To je možné zakázat pomocí argumentu stringsAsFactors=, případně as.is=.1)

Informace o faktorech

levels()
nlevels()
table()
is.factor()

Změna pořadí úrovní faktoru

Nyní nakreslíme první graf s faktorem. Nejprve vytvoříme cvičná data. Do objektu y necháme vygenerovat 20 hodnot ze 4 množin normálně rozložených hodnot s průměry 2, 4, 1 a 3 (5 hodnot z každé)2) a směrodatnou odchylkou 1. Do objektu gr pak vytvořím faktor s úrovňemi A, B, C, D. set.seed() slouží nastavení startovní pozice (semene) pro generování náhodných čísel. Pokud si jej nastavíte na 5 stejně jako já, měli byste dostat identický výsledek. Nakonec nechám zobrazit graf závislosti y na gr. Protože gr je faktor (kategoriální proměnná), automaticky R kreslí krabicový graf (box-plot).

set.seed(5)
y<- rnorm(20, mean = c(2, 4, 1, 3))
gr<- factor(rep(LETTERS[1:4], 5))
plot(y ~ gr)

Krabičky jsou pěkně neuspořádané, jedna dole, pak nahoře, pak zase dole a nakonec nahoře. Přehlednější by byl graf s krabičkami seřazenými podle jejich pozice na Y ose. Na první pohled by bylo vidět, které úrovně faktoru gr mají nízké hodnoty y, a které vysoké.

Manuální změna pořadí úrovní

Manuálního seřazení dosáhneme pomocí funkce factor(), kde do argumentu levels= vyjmenujeme úrovně faktoru v požadovaném pořadí. V našem případě by to mohlo být pořadí C, A, D, B, aby krabičky byly od nejnižší po nejvyšší:

gr2<- factor(gr, levels= c('C', 'A', 'D', 'B'))
plot(y ~ gr2)

Všimněte si, že krabičky se níjak nezměnily, jen se i s popiskami popřesouvaly. Nedošlo k žádné změně dat či příslušnosti hodnot y do skupin gr, jen se změnilo pořadí úrovní. Zde jsou původní faktor gr a nově vytvořený faktor gr2 se změněným pořadím úrovní:

gr
 [1] A B C D A B C D A B C D A B C D A B C D
Levels: A B C D
gr2
 [1] A B C D A B C D A B C D A B C D A B C D
Levels: C A D B

Samozřejmě, ještě se musely změnit numerické hodnoty odkazující na úrovně faktoru, protože se změnilo jejich pořadí. A to právě zapříčiňuje, že se krabičky poposouvaly. Změnila se numerická reprezentace faktoru:

as.numeric(gr)
 [1] 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
as.numeric(gr2)
 [1] 2 4 1 3 2 4 1 3 2 4 1 3 2 4 1 3 2 4 1 3

Automatické přeřazení úrovní podle proměnné

V předchozím příkladu jsme úrovně faktoru seřadili manuálně podle hodnot y tak, aby skupiny s nejnižšími hodnotami byly první a ty s nejvyššími poslední. Stejného dosáhneme i pomocí funkce reorder(), do níž zadáme, podle které proměnné se mají úrovně faktoru seřadit a jaká statistika se má k tomu použít. Vzpomeňte, že pro každou skupinu máme naměřených několik hodnot, v našem případě je to 5 pro každou skupinu. Těch 5 hodnot je potřeba sumarizovat do jedné hodnoty, která bude zodpovědná za pořadí úrovní. Rozumné bude použití střední hodnoty, kterou v box-plotu reprezentuje silná vodorovná čára – medián. Mohli bychom ale použít jakoukoli, i vlastní nadefinovanou funkci a klidně řadit úrovně i podle hodnot jiné proměnné, pokud k tomu máme důvod.

par(mfrow=c(1,2)) # rozdělí grafické okno na 2 vedle sebe
 
# seřazení úrovní gr od nejnižšího po nejvyšší medián y:
gr3<- reorder(gr, y, FUN= median)
 
# a od nejvyššího po nejnižší:
gr4<- reorder(gr, -y, FUN= median)
 
plot(y ~ gr3)
plot(y ~ gr4)

Nastavení referenční - první úrovně

Někdy nám nezáleží na pořadí všech úrovní, jen potřebujeme nastavit jednu úroveň jako první - referenční. Například při hodnocení experimentů, kdy chceme vůči kontrole porovnávat ostatní experimentální skupiny. Nastavení referenční skupiny je samozřejmě možné manuálně, ale slouží k tomu také funkce relevel(). Aplikujeme ji na faktor a jen zvolíme referenční úroveň. Představme si, že ve faktoru gr je skupina C referenční (C jako control), proto ji chceme posunout na první místo. Dosáhneme toho následovně:

gr5<- relevel(gr, "C")
plot(y ~ gr5)

Změna názvů úrovní

Často máme úrovně pojmenované pracovními názvy, ale do publikace nebo diplomové práce by bylo dobré, aby úrovně v grafech byly smysluplně a hezky označené. Popisky v grafech bychom sice mohli změnit při malování grafu, ale museli bychom to opakovat při každém grafu dokola. Jednodušší je úrovně prostě přejmenovat.

Máme dvě možnosti:

levels()<-
Jednak můžeme přepsat úrovně již existujícího faktoru:

levels(gr)<- c("Alpha", "Beta", "Control", "Delta")

Takto můžeme přejmenovat i jen vybranou úroveň/vybrané úrovně. Například ponechat A, B a D, ale C změnit na Control:

levels(gr)[3]<- "Control"
# případně:
levels(gr)[levels(gr) == "C"]<- "Control"

factor(..., labels= )
Druhou možností je změna názvů úrovní během tvorby nového faktoru, již zajistí argument labels= funkce factor(). Tento postup použijeme především při tvorbě faktorů z jakýchkoli vektorů, ale můžeme jej aplikovat i na již existující faktor:

# použití na faktoru:
factor(gr, labels= c("Alpha", "Beta", "Control", "Delta"))
 [1] Alpha   Beta    Control Delta   Alpha   Beta    Control Delta   Alpha   Beta   
[11] Control Delta   Alpha   Beta    Control Delta   Alpha   Beta    Control Delta  
Levels: Alpha Beta Control Delta
 
# při tvorbě faktoru z textového vektoru:
factor(rep(LETTERS[1:4], 5), labels= c("Alpha", "Beta", "Control", "Delta"))
 [1] Alpha   Beta    Control Delta   Alpha   Beta    Control Delta   Alpha   Beta   
[11] Control Delta   Alpha   Beta    Control Delta   Alpha   Beta    Control Delta  
Levels: Alpha Beta Control Delta
 
# při tvorbě faktoru z logického vektoru:
factor(y > 2, labels= c("small", "big"))
 [1] small big   small big   big   big   small big   small big   big   big   small big  
[15] small big   small small small big  
Levels: small big

V obou případech je potřeba dát pozor na pořadí úrovní, abychom při přejmenování omylem nezměnili jejich význam a například neudělali z B Deltu.

Spojení úrovní faktoru

Přiřadíme-li pomocí levels()<- dvěma nebo více úrovním stejnou hodnotu, čili pojmenujele-li je stejně, dojde k jejich sloučení. Sloučení úrovní A, B a D do jedné Effect a přejmenování C na Control bychom dosáhli takto:

# vytvoření kopie gr (gr chceme zachovat)
gr6<- gr
 
# původní úrovně faktoru gr6:
levels(gr6)
[1] "A" "B" "C" "D"
 
# přejmenování úrovní gr6 se sloučením A, B a D do Effect:
levels(gr6)<- c("Effect", "Effect", "Control", "Effect")
gr6
 [1] Effect  Effect  Control Effect  Effect  Effect  Control Effect 
 [9] Effect  Effect  Control Effect  Effect  Effect  Control Effect 
[17] Effect  Effect  Control Effect 
Levels: Effect Control

Sloučení přejmenováním je možné jen pomocí levels()<-, nikoliv factor(..., labels=)

Další možností je použít funkci combine_factor() balíku reshape. Její výhodou je, že se nemusíte starat o pořadí úrovní, jen specifikujete, které úrovně chcete sloučit do jakých. Balík reshape však není v základní instalaci R, proto je před použitím funkce combine_factor() potřeba jej nainstalovat a připojit jeho knihovnu. Vyzkoušení funkce combine_factor() ponechám na vás.

Vytvoření faktoru z kontinuální proměnné

Někdy se hodí rozdělení případů (vzorků) do skupin podle nějaké kontinuální proměnné. Například se může stát, že gradient pH, který jsme měřili na kontinuální škále, nemáme dobře pokrytý a máme vzorky jen z kyselých lokalit s pH 3–5, a pak až z bazických s pH 7–9. Protože střední část gradientu nám úplně chybí, není dobré jej použít jako kontinuální proměnnou, ale spíš jako kategoriální (faktor) s 2 skupinami (úrovněmi) – kyselé a bazické lokality.

Opět je víc možností, jak z kontinuální proměnné udělat faktor. Manuálně to můžeme provést pomocí logického výrazu, který nám lokality rozdělí na ty s pH nižším a vyšším, než je námi zvolená hranice. Výsledek pak převedeme na faktor pomocí funkce factor(), přičemž můžeme změnit úrovně z FALSE a TRUE na např. low a high:

# umělý "gradient" pH:
set.seed(5)
pH<- round(runif(30, min= c(3,7), max= c(5,9)), 2)
 
# zobrazení hodnot pH podle jejich pořadí - pro představu
dotchart(pH)




Na obrázku jsou pomocí funkce dotchart() vyneseny hodnoty pH (osa X) podle jejich pořadí (osa Y), jak byly vygenerovány.

# převedení pH na faktor, vzorky s pH > 6 budou označeny jako "high"
factor(pH > 6, labels= c("low", "high"))
 [1] low  high low  high low  high low  high low  high low  high low  high low  high low 
[18] high low  high low  high low  high low  high low  high low  high
Levels: low high

Logické hodnoty můžeme sčítat (FALSE = 0 a TRUE = 1). To nám umožňuje vytvořit faktor i o více než dvou úrovních. Například můžeme ještě ze skupin low a high oddělit “extrémně” nízké a vysoké hodnoty, např. nižší nebo rovné 3,5 a vyšší než 8,5:

factor((pH > 3.5) + (pH > 6) + (pH > 8.5), labels= c("Elow", "low", "high", "Ehigh"))
 [1] Elow  high  low   high  Elow  high  low   Ehigh low   high  low   high  low   high 
[15] low   high  low   Ehigh low   Ehigh low   high  Elow  high  Elow  high  low   Ehigh
[29] Elow  Ehigh
Levels: Elow low high Ehigh

Pro tvorbu faktorů o více než 2 úrovních je uživatelsky příjemnější a také přehlednější použití funkce cut(), která je pro to dělaná. Prvním argumentem funkce cut() je vektor, který chceme “nařezat” x=, a pak jsou to breaks= – buď počet úrovní, jež má mít výsledný faktor, nebo vektor hraničních hodnot výsledných úrovní, a to včetně mezních. Můžeme zadat i názvy úrovní tvořeného faktoru labels=. Pokud zadáme počet výsledných úrovní, funkce cut() nařeže proměnnou rovnoměrně po stejných dílech. Abychom zopakovali výsledek předchozího kroku, musíme však hraniční hodnoty zadat manuálně.
Zde je potřeba dát pozor na mezní hodnoty. Funkce cut() zahrnuje do dané skupiny vždy hodnoty větší než její spodní hraniční hodnota. Pokud jsme jako nejnižší hraniční hodnotu zadali minimální hodnotu kontinuální proměnné, ta není větší než ona hraniční hodnota, ona je jí rovna. Aby tedy nejnižší hodnota spadla do skupiny nejnižších hodnot, musíme buď mezní hodnotu maličko snížit, nebo použít ještě argument include.lowest= T.

# cut() s nezařazenou nejnižší hodnotou (5. hodnota je nyní NA)
cut(pH, breaks= c(min(pH), 3.5, 6, 8.5, max(pH)), labels= c("Elow", "low", "high", "Ehigh"))
 [1] Elow  high  low   high  <NA>  high  low   Ehigh low   high  low   high  low   high 
[15] low   high  low   Ehigh low   Ehigh low   high  Elow  high  Elow  high  low   Ehigh
[29] Elow  Ehigh
Levels: Elow low high Ehigh
 
# cut() s argumentem include.lowest= T
cut(pH, breaks= c(min(pH), 3.5, 6, 8.5, max(pH)), labels= c("Elow", "low", "high", "Ehigh"), 
    include.lowest= T)
 [1] Elow  high  low   high  Elow  high  low   Ehigh low   high  low   high  low   high 
[15] low   high  low   Ehigh low   Ehigh low   high  Elow  high  Elow  high  low   Ehigh
[29] Elow  Ehigh
Levels: Elow low high Ehigh
1)
V tibble() dataframech v rámci filozofie tidyverse tomu tak není.
2)
Prvním argumentem funkce rnorm() volíme počet hodnot, které chceme vygenerovat, to je těch 20. mean= c(2, 4, 1, 3) pak specifikuje 4 průměry množin, ze kterých chceme hodnoty generovat. Protože chceme vrátit 20 hodnot, ale zadali jsme jen 4 průměry, průměry se zreplikují na délku 20. Pátá vrácená hodnota tedy bude vytažena z množiny hodnot, jejichž průměr je 2, 6. pak z množiny s průměrem 4, atd.
r_intro/cs/theory/factor.txt · Last modified: 2018/06/01 15:26 by vitek