R Language
faktorer
Sök…
Syntax
- faktor (x = tecken (), nivåer, etiketter = nivåer, utesluter = NA, ordnad = är. ordnad (x), nmax = NA)
- Kör
?factor
eller se dokumentationen online.
Anmärkningar
Ett objekt med klass factor
är en vektor med en särskild uppsättning av egenskaper.
- Det lagras internt som en
integer
. - Det upprätthåller ett
levels
attribut som visar teckenrepresentation av värden. - Dess klass lagras som
factor
För att illustrera, låt oss generera en vektor med 1 000 observationer från en uppsättning färger.
set.seed(1)
Color <- sample(x = c("Red", "Blue", "Green", "Yellow"),
size = 1000,
replace = TRUE)
Color <- factor(Color)
Vi kan observera var och en av egenskaperna hos Color
listas ovan:
#* 1. It is stored internally as an `integer` vector
typeof(Color)
[1] "integer"
#* 2. It maintains a `levels` attribute the shows the character representation of the values.
#* 3. Its class is stored as `factor`
attributes(Color)
$levels [1] "Blue" "Green" "Red" "Yellow" $class [1] "factor"
Den främsta fördelen med ett faktorobjekt är effektiviteten i datalagring. Ett heltal kräver mindre minne för att lagra än ett tecken. Sådan effektivitet var mycket önskvärd när många datorer hade mycket mer begränsade resurser än nuvarande maskiner (för en mer detaljerad historia om motivationen bakom att använda faktorer, se stringsAsFactors
: en obehörig biografi ). Skillnaden i minnesanvändning kan ses även i vårt Color
. Som du kan se kräver lagring av Color
som tecken ungefär 1,7 gånger så mycket minne som faktorobjektet.
#* Amount of memory required to store Color as a factor.
object.size(Color)
4624 bytes
#* Amount of memory required to store Color as a character
object.size(as.character(Color))
8232 bytes
Kartlägga heltalet till nivån
Medan den interna beräkningen av faktorer ser objektet som ett heltal, är den önskade representationen för mänsklig konsumtion karaktärsnivån. Till exempel,
head(Color)
[1] Blue Blue Green Yellow Red Yellow Levels: Blue Green Red Yellow
är enklare för mänsklig förståelse än
head(as.numeric(Color))
[1] 1 1 2 4 3 4
En ungefärlig illustration av hur R går till att matcha teckenrepresentationen till det interna heltalet är:
head(levels(Color)[as.numeric(Color)])
[1] "Blue" "Blue" "Green" "Yellow" "Red" "Yellow"
Jämför dessa resultat med
head(Color)
[1] Blue Blue Green Yellow Red Yellow Levels: Blue Green Red Yellow
Modern användning av faktorer
2007 introducerade R en hashmetod för tecken som minskade minnesbördan för karaktärvektorer (ref: stringsAsFactors
: an Unauthorised Biography ). Observera att när vi bestämde att tecken kräver 1,7 gånger mer lagringsutrymme än faktorer, beräknades det i en ny version av R, vilket innebar att minnesanvändningen av teckenvektorer var ännu mer beskattande före 2007.
På grund av hasningsmetoden i modern R och mycket större minnesresurser i moderna datorer har frågan om minneseffektivitet vid lagring av teckenvärden reducerats till ett mycket litet problem. Den rådande inställningen i R-gemenskapen är en preferens för karaktärvektorer framför faktorer i de flesta situationer. De främsta orsakerna till förskjutningen från faktorer är
- Ökningen av ostrukturerad och / eller löst kontrollerad karaktärsinformation
- Faktorns tendens att inte uppträda som önskat när användaren glömmer att hon har att göra med en faktor och inte en karaktär
I det första fallet är det meningslöst att lagra fri text eller öppna svarfält som faktorer, eftersom det troligtvis kommer att finnas något mönster som möjliggör mer än en observation per nivå. Alternativt, om datastrukturen inte kontrolleras noggrant, är det möjligt att få flera nivåer som motsvarar samma kategori (t.ex. "blå", "blå" och "blå"). I sådana fall föredrar många att hantera dessa avvikelser som tecken innan de konverteras till en faktor (om konvertering sker alls).
I det andra fallet, om användaren tror att hon arbetar med en teckenvektor, kanske vissa metoder inte svarar som förväntat. Denna grundläggande förståelse kan leda till förvirring och frustration när du försöker felsöka skript och koder. Även om detta kan ses som användarens fel, är de flesta användare gärna undvika att använda faktorer och helt undvika dessa situationer.
Grundläggande skapande av faktorer
Faktorer är ett sätt att representera kategoriska variabler i R. En faktor lagras internt som en heltalsvektor . De unika elementen i den medföljande karaktärvektorn är kända som faktorens nivåer . Som standard, om nivåerna inte tillhandahålls av användaren, kommer R att generera uppsättningen unika värden i vektorn, sortera dessa värden alfanumeriskt och använda dem som nivåer.
charvar <- rep(c("n", "c"), each = 3)
f <- factor(charvar)
f
levels(f)
> f
[1] n n n c c c
Levels: c n
> levels(f)
[1] "c" "n"
Om du vill ändra nivåns ordning är det ett alternativ att ange nivåerna manuellt:
levels(factor(charvar, levels = c("n","c")))
> levels(factor(charvar, levels = c("n","c")))
[1] "n" "c"
Faktorer har ett antal egenskaper. Nivåer kan till exempel ges etiketter:
> f <- factor(charvar, levels=c("n", "c"), labels=c("Newt", "Capybara"))
> f
[1] Newt Newt Newt Capybara Capybara Capybara
Levels: Newt Capybara
En annan egenskap som kan tilldelas är om faktorn är beställd:
> Weekdays <- factor(c("Monday", "Wednesday", "Thursday", "Tuesday", "Friday", "Sunday", "Saturday"))
> Weekdays
[1] Monday Wednesday Thursday Tuesday Friday Sunday Saturday
Levels: Friday Monday Saturday Sunday Thursday Tuesday Wednesday
> Weekdays <- factor(Weekdays, levels=c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"), ordered=TRUE)
> Weekdays
[1] Monday Wednesday Thursday Tuesday Friday Sunday Saturday
Levels: Monday < Tuesday < Wednesday < Thursday < Friday < Saturday < Sunday
När en nivå av faktorn inte längre används kan du släppa den med hjälp av droplevels()
-funktionen:
> Weekend <- subset(Weekdays, Weekdays == "Saturday" | Weekdays == "Sunday")
> Weekend
[1] Sunday Saturday
Levels: Monday < Tuesday < Wednesday < Thursday < Friday < Saturday < Sunday
> Weekend <- droplevels(Weekend)
> Weekend
[1] Sunday Saturday
Levels: Saturday < Sunday
Konsolidera faktornivåer med en lista
Det finns tider då det är önskvärt att konsolidera faktornivåer i färre grupper, kanske på grund av glesa uppgifter i en av kategorierna. Det kan också uppstå när du har olika stavningar eller bokstäver av kategorinamn. Betrakta som ett exempel på faktorn
set.seed(1)
colorful <- sample(c("red", "Red", "RED", "blue", "Blue", "BLUE", "green", "gren"),
size = 20,
replace = TRUE)
colorful <- factor(colorful)
Eftersom R är skiftlägeskänslig, skulle en frekvensstabell för denna vektor visas som nedan.
table(colorful)
colorful blue Blue BLUE green gren red Red RED 3 1 4 2 4 1 3 2
Denna tabell representerar emellertid inte den verkliga fördelningen av data, och kategorierna kan faktiskt reduceras till tre typer: Blått, Grönt och Rött. Tre exempel ges. Den första illustrerar vad som verkar som en uppenbar lösning, men kommer faktiskt inte att ge en lösning. Den andra ger en fungerande lösning, men är ordbaserad och beräkningsbar. Den tredje är inte en uppenbar lösning, men är relativt kompakt och beräkningseffektiv.
Konsolidera nivåer med hjälp av factor
( factor_approach
)
factor(as.character(colorful),
levels = c("blue", "Blue", "BLUE", "green", "gren", "red", "Red", "RED"),
labels = c("Blue", "Blue", "Blue", "Green", "Green", "Red", "Red", "Red"))
[1] Green Blue Red Red Blue Red Red Red Blue Red Green Green Green Blue Red Green [17] Red Green Green Red Levels: Blue Blue Blue Green Green Red Red Red Warning message: In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) else paste0(labels, : duplicated levels in factors are deprecated
Lägg märke till att det finns duplicerade nivåer. Vi har fortfarande tre kategorier för "Blue", som inte fullbordar vår uppgift att konsolidera nivåer. Dessutom finns det en varning om att duplicerade nivåer avskrivs, vilket innebär att den här koden kan generera ett fel i framtiden.
Konsolidera nivåer med ifelse
( ifelse_approach
)
factor(ifelse(colorful %in% c("blue", "Blue", "BLUE"),
"Blue",
ifelse(colorful %in% c("green", "gren"),
"Green",
"Red")))
[1] Green Blue Red Red Blue Red Red Red Blue Red Green Green Green Blue Red Green [17] Red Green Green Red Levels: Blue Green Red
Den här koden genererar önskat resultat men kräver användning av kapslade ifelse
uttalanden. Det finns inget fel med den här metoden, ifelse
hantering av kapslade ifelse
uttalanden kan vara en tråkig uppgift och måste göras noggrant.
Konsolidera faktornivåer med en lista ( list_approach
)
Ett mindre uppenbart sätt att konsolidera nivåer är att använda en lista där namnet på varje element är det önskade kategorinamnet och elementet är en teckenvektor för nivåerna i faktorn som ska kartlägga den önskade kategorin. Detta har den extra fördelen att arbeta direkt på levels
attribut för faktorn utan att behöva tilldela nya objekt.
levels(colorful) <-
list("Blue" = c("blue", "Blue", "BLUE"),
"Green" = c("green", "gren"),
"Red" = c("red", "Red", "RED"))
[1] Green Blue Red Red Blue Red Red Red Blue Red Green Green Green Blue Red Green [17] Red Green Green Red Levels: Blue Green Red
Utjämning av varje strategi
Den tid som krävs för att utföra vart och ett av dessa tillvägagångssätt sammanfattas nedan. (För rymdens skull visas inte koden för att generera den här sammanfattningen)
Unit: microseconds expr min lq mean median uq max neval cld factor 78.725 83.256 93.26023 87.5030 97.131 218.899 100 b ifelse 104.494 107.609 123.53793 113.4145 128.281 254.580 100 c list_approach 49.557 52.955 60.50756 54.9370 65.132 138.193 100 a
Listmetoden går ungefär dubbelt så snabbt som ifelse
metoden. Men förutom i tider med mycket, mycket stora mängder data kommer skillnaderna i exekveringstid sannolikt att mätas antingen i mikrosekunder eller millisekunder. Med så små tidsskillnader behöver effektiviteten inte vägleda beslutet om vilken metod att använda. Använd istället en metod som är bekant och bekväm och som du och dina medarbetare kommer att förstå vid framtida granskning.
faktorer
Faktorer är en metod för att representera kategoriska variabler i R. Givet en vektor x
vars värden kan konverteras till tecken med hjälp av as.character()
, as.character()
standardargumenten för factor()
och as.factor()
ett heltal till varje distinkt element i vektorn såväl som ett nivåattribut och ett etikettattribut. Nivåer är värdena x
kan ta och etiketter kan antingen vara det givna elementet eller bestämmas av användaren.
Till exempel hur faktorer fungerar skapar vi en faktor med standardattribut, sedan anpassade nivåer och sedan anpassade nivåer och etiketter.
# standard
factor(c(1,1,2,2,3,3))
[1] 1 1 2 2 3 3
Levels: 1 2 3
Det kan uppstå fall där användaren vet hur många möjliga värden en faktor kan ta på sig är större än de aktuella värdena i vektorn. För detta tilldelar vi själva nivåerna i factor()
.
factor(c(1,1,2,2,3,3),
levels = c(1,2,3,4,5))
[1] 1 1 2 2 3 3
Levels: 1 2 3 4 5
För stiländamål kanske användaren vill tilldela etiketter till varje nivå. Som standard är etiketter teckenrepresentation av nivåerna. Här tilldelar vi etiketter för alla möjliga nivåer i faktorn.
factor(c(1,1,2,2,3,3),
levels = c(1,2,3,4,5),
labels = c("Fox","Dog","Cow","Brick","Dolphin"))
[1] Fox Fox Dog Dog Cow Cow
Levels: Fox Dog Cow Brick Dolphin
Normalt kan faktorer bara jämföras med ==
och !=
Och om faktorerna har samma nivåer. Följande jämförelse av faktorer misslyckas även om de verkar lika eftersom faktorerna har olika faktornivåer.
factor(c(1,1,2,2,3,3),levels = c(1,2,3)) == factor(c(1,1,2,2,3,3),levels = c(1,2,3,4,5))
Error in Ops.factor(factor(c(1, 1, 2, 2, 3, 3), levels = c(1, 2, 3)), :
level sets of factors are different
Detta är meningsfullt eftersom de extra nivåerna i RHS betyder att R inte har tillräckligt med information om varje faktor för att jämföra dem på ett meningsfullt sätt.
Operatörerna <
, <=
, >
och >=
kan endast användas för beställda faktorer. Dessa kan representera kategoriska värden som fortfarande har en linjär ordning. En ordnad faktor kan skapas genom att tillhandahålla den ordered = TRUE
argument till factor
funktionen eller bara använda ordered
funktionen.
x <- factor(1:3, labels = c('low', 'medium', 'high'), ordered = TRUE)
print(x)
[1] low medium high
Levels: low < medium < high
y <- ordered(3:1, labels = c('low', 'medium', 'high'))
print(y)
[1] high medium low
Levels: low < medium < high
x < y
[1] TRUE FALSE FALSE
Mer information finns i faktordokumentationen .
Ändra och ändra om faktorer
När faktorer skapas med standardvärden, bildas levels
av as.character
tillämpas på ingångarna och ordnas alfabetiskt.
charvar <- rep(c("W", "n", "c"), times=c(17,20,14))
f <- factor(charvar)
levels(f)
# [1] "c" "n" "W"
I vissa situationer är behandlingen av standardbeställningen av levels
(alfabetisk / leksikalisk ordning) acceptabel. Om man till exempel vill plot
frekvenserna kommer detta att bli resultatet:
plot(f,col=1:length(levels(f)))
Men om vi vill ha en annan beställning av levels
måste vi ange detta i levels
eller labels
parameter (ta hand att innebörden av "ordning" här skiljer sig från beställda faktorer, se nedan). Det finns många alternativ att utföra den uppgiften beroende på situationen.
1. Definiera omfaktorn
När det är möjligt, kan vi återskapa den faktor med hjälp av levels
parameter med den ordning som vi vill ha.
ff <- factor(charvar, levels = c("n", "W", "c"))
levels(ff)
# [1] "n" "W" "c"
gg <- factor(charvar, levels = c("W", "c", "n"))
levels(gg)
# [1] "W" "c" "n"
När ingångsnivåerna är annorlunda än de önskade utgångsnivåer, använder vi labels
parameter som orsakar de levels
parameter att bli ett "filter" för acceptabla ingångsvärden, men lämnar de slutliga värdena på "nivåer" för faktorn vektorn som argument till labels
:
fm <- factor(as.numeric(f),levels = c(2,3,1),
labels = c("nn", "WW", "cc"))
levels(fm)
# [1] "nn" "WW" "cc"
fm <- factor(LETTERS[1:6], levels = LETTERS[1:4], # only 'A'-'D' as input
labels = letters[1:4]) # but assigned to 'a'-'d'
fm
#[1] a b c d <NA> <NA>
#Levels: a b c d
2. Använd relevel
funktion
När det finns en specifik level
som måste vara den första kan vi använda relevel
. Detta händer till exempel i samband med statistisk analys, när en base
kategorin är nödvändig för att testa hypotesen.
g<-relevel(f, "n") # moves n to be the first level
levels(g)
# [1] "n" "c" "W"
Som kan verifieras är f
och g
densamma
all.equal(f, g)
# [1] "Attributes: < Component “levels”: 2 string mismatches >"
all.equal(f, g, check.attributes = F)
# [1] TRUE
3. Ombeställning av faktorer
Det finns fall då vi måste reorder
om levels
baserade på ett tal, ett partiellt resultat, en beräknad statistik eller tidigare beräkningar. Låt oss ordna om baserat på levels
frekvenser
table(g)
# g
# n c W
# 20 14 17
reorder
är generisk (se help(reorder)
), men i detta sammanhang behöver: x
, i detta fall faktorn; X
, ett numeriskt värde med samma längd som x
; och FUN
, en funktion som ska tillämpas på X
och beräknas med nivån på x
, som bestämmer levels
, som standard ökar. Resultatet är samma faktor med nivåerna omordnade.
g.ord <- reorder(g,rep(1,length(g)), FUN=sum) #increasing
levels(g.ord)
# [1] "c" "W" "n"
För att få en minskande ordning överväger vi negativa värden ( -1
)
g.ord.d <- reorder(g,rep(-1,length(g)), FUN=sum)
levels(g.ord.d)
# [1] "n" "W" "c"
Återigen är faktorn densamma som de andra.
data.frame(f,g,g.ord,g.ord.d)[seq(1,length(g),by=5),] #just same lines
# f g g.ord g.ord.d
# 1 W W W W
# 6 W W W W
# 11 W W W W
# 16 W W W W
# 21 n n n n
# 26 n n n n
# 31 n n n n
# 36 n n n n
# 41 c c c c
# 46 c c c c
# 51 c c c c
När det finns en kvantitativ variabel relaterad till faktorvariabeln, kan vi använda andra funktioner för att ordna levels
. Låter ta iris
( help("iris")
för mer information), för att ordna om Species
faktorn med hjälp av dess genomsnittliga Sepal.Width
.
miris <- iris #help("iris") # copy the data
with(miris, tapply(Sepal.Width,Species,mean))
# setosa versicolor virginica
# 3.428 2.770 2.974
miris$Species.o<-with(miris,reorder(Species,-Sepal.Width))
levels(miris$Species.o)
# [1] "setosa" "virginica" "versicolor"
Den vanliga boxplot
(säg: with(miris, boxplot(Petal.Width~Species)
) kommer att visa especiesna i denna ordning: setosa , versicolor och virginica . Men med den beställda faktorn får vi beställda arter med dess medelvärde Sepal.Width
:
boxplot(Petal.Width~Species.o, data = miris,
xlab = "Species", ylab = "Petal Width",
main = "Iris Data, ordered by mean sepal width", varwidth = TRUE,
col = 2:4)
Dessutom är det också möjligt att ändra namn på levels
, kombinera dem i grupper eller lägga till nya levels
. För det använder vi funktionen för samma levels
.
f1<-f
levels(f1)
# [1] "c" "n" "W"
levels(f1) <- c("upper","upper","CAP") #rename and grouping
levels(f1)
# [1] "upper" "CAP"
f2<-f1
levels(f2) <- c("upper","CAP", "Number") #add Number level, which is empty
levels(f2)
# [1] "upper" "CAP" "Number"
f2[length(f2):(length(f2)+5)]<-"Number" # add cases for the new level
table(f2)
# f2
# upper CAP Number
# 33 17 6
f3<-f1
levels(f3) <- list(G1 = "upper", G2 = "CAP", G3 = "Number") # The same using list
levels(f3)
# [1] "G1" "G2" "G3"
f3[length(f3):(length(f3)+6)]<-"G3" ## add cases for the new level
table(f3)
# f3
# G1 G2 G3
# 33 17 7
- Beställda faktorer
Slutligen vet vi att ordered
faktorer skiljer sig från factors
, den första används för att representera ordinära data och den andra som arbetar med nominella data . Till att börja med är det inte meningsfullt att ändra levels
för levels
för ordnade faktorer, men vi kan ändra dess labels
.
ordvar<-rep(c("Low", "Medium", "High"), times=c(7,2,4))
of<-ordered(ordvar,levels=c("Low", "Medium", "High"))
levels(of)
# [1] "Low" "Medium" "High"
of1<-of
levels(of1)<- c("LOW", "MEDIUM", "HIGH")
levels(of1)
# [1] "LOW" "MEDIUM" "HIGH"
is.ordered(of1)
# [1] TRUE
of1
# [1] LOW LOW LOW LOW LOW LOW LOW MEDIUM MEDIUM HIGH HIGH HIGH HIGH
# Levels: LOW < MEDIUM < HIGH
Ombyggnadsfaktorer från noll
Problem
Faktorer används för att representera variabler som tar värden från en uppsättning kategorier, kända som Nivåer i R. Till exempel kan vissa experiment kännetecknas av energinivån för ett batteri, med fyra nivåer: tom, låg, normal och full. Sedan, för 5 olika provtagningsplatser, kunde dessa nivåer identifieras, i dessa termer, enligt följande:
full , full , normal , tom , låg
I databaser eller andra informationskällor är vanligtvis hanteringen av dessa data med godtyckliga heltalindex associerade med kategorierna eller nivåerna. Om vi antar att för det givna exemplet skulle vi tilldela indexen enligt följande: 1 = tom, 2 = låg, 3 = normal, 4 = full, så kan de 5 proverna kodas som:
4 , 4 , 3 , 1 , 2
Det kan hända att du från din informationskälla, t.ex. en databas, bara har den kodade listan med heltal och katalogen som associerar varje heltal med varje nivå-nyckelord. Hur kan en faktor R rekonstrueras från den informationen?
Lösning
Vi kommer att simulera en vektor med 20 heltal som representerar proverna, som var och en kan ha ett av fyra olika värden:
set.seed(18)
ii <- sample(1:4, 20, replace=T)
ii
[1] 4 3 4 1 1 3 2 3 2 1 3 4 1 2 4 1 3 1 4 1
Det första steget är att skapa en faktor från den föregående sekvensen, där nivåerna eller kategorierna exakt är siffrorna från 1 till 4.
fii <- factor(ii, levels=1:4) # it is necessary to indicate the numeric levels
fii
[1] 4 3 4 1 1 3 2 3 2 1 3 4 1 2 4 1 3 1 4 1
Nivåer: 1 2 3 4
Nu måste du klä på faktorn som redan skapats med indextaggarna:
levels(fii) <- c("empty", "low", "normal", "full")
fii
[1] full normal full tom tom normal låg normal låg tom
[11] normal full tom låg tom full normal tom full tom
Nivåer: tom låg normal full