Sök…


Syntax

  1. faktor (x = tecken (), nivåer, etiketter = nivåer, utesluter = NA, ordnad = är. ordnad (x), nmax = NA)
  2. 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.

  1. Det lagras internt som en integer .
  2. Det upprätthåller ett levels attribut som visar teckenrepresentation av värden.
  3. 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

  1. Ökningen av ostrukturerad och / eller löst kontrollerad karaktärsinformation
  2. 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)))

ange bildbeskrivning här

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) 

ange bildbeskrivning här

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



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow