Zoeken…


Syntaxis

  1. factor (x = teken (), niveaus, labels = niveaus, uitsluiten = NA, geordend = is geordend (x), nmax = NA)
  2. Run ?factor of bekijk de documentatie online.

Opmerkingen

Een object met factor is een vector met een bepaalde set kenmerken.

  1. Het wordt intern opgeslagen als een integer vector.
  2. Het behoudt een levels toont de karakterrepresentatie van de waarden.
  3. De klasse wordt opgeslagen als factor

Laten we ter illustratie een vector van 1.000 observaties genereren uit een set kleuren.

set.seed(1)
Color <- sample(x = c("Red", "Blue", "Green", "Yellow"), 
                size = 1000, 
                replace = TRUE)
Color <- factor(Color)

We kunnen elk van de hierboven genoemde kenmerken van Color observeren:

#* 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"

Het primaire voordeel van een factorobject is efficiëntie bij gegevensopslag. Een geheel getal heeft minder geheugen nodig om op te slaan dan een karakter. Een dergelijke efficiëntie was zeer wenselijk wanneer veel computers veel beperktere middelen hadden dan huidige machines (voor een meer gedetailleerde geschiedenis van de motivaties achter het gebruik van factoren, zie stringsAsFactors : an Unauthorized Biography ). Het verschil in geheugengebruik is zelfs zichtbaar in ons object Color . Zoals je ziet, vereist het opslaan van Color als een personage ongeveer 1,7 keer zoveel geheugen als het factorobject.

#* 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

Het gehele getal in kaart brengen

Terwijl de interne berekening van factoren het object als een geheel getal ziet, is de gewenste weergave voor menselijke consumptie het tekenniveau. Bijvoorbeeld,

head(Color)
[1] Blue   Blue   Green  Yellow Red    Yellow  
Levels: Blue Green Red Yellow

is gemakkelijker voor het menselijk begrip dan

head(as.numeric(Color))
[1] 1 1 2 4 3 4

Een illustratie bij benadering van hoe R de tekenrepresentatie aanpast aan de interne gehele waarde is:

head(levels(Color)[as.numeric(Color)])
[1] "Blue"   "Blue"   "Green"  "Yellow" "Red"    "Yellow"

Vergelijk deze resultaten met

head(Color)
[1] Blue   Blue   Green  Yellow Red    Yellow  
Levels: Blue Green Red Yellow

Modern gebruik van factoren

In 2007 introduceerde R een hash-methode voor tekens om de geheugenlast van stringsAsFactors verminderen (ref: stringsAsFactors : an Unauthorized Biography ). Merk op dat toen we bepaalden dat karakters 1,7 keer meer opslagruimte nodig hebben dan factoren, dat werd berekend in een recente versie van R, wat betekent dat het geheugengebruik van karaktervectoren nog zwaarder was vóór 2007.

Vanwege de hashing-methode in moderne R en veel grotere geheugenbronnen in moderne computers, is de kwestie van geheugenefficiëntie bij het opslaan van karakterwaarden teruggebracht tot een zeer kleine zorg. De heersende houding in de R-Gemeenschap is een voorkeur voor karaktervectoren boven factoren in de meeste situaties. De belangrijkste oorzaken voor de verschuiving van factoren zijn

  1. De toename van ongestructureerde en / of los gecontroleerde karaktergegevens
  2. De neiging van factoren om zich niet naar wens te gedragen wanneer de gebruiker vergeet dat ze te maken heeft met een factor en niet met een personage

In het eerste geval heeft het geen zin om vrije tekst of open responsvelden als factoren op te slaan, omdat er onwaarschijnlijk een patroon is dat meer dan één observatie per niveau mogelijk maakt. Als alternatief, als de gegevensstructuur niet zorgvuldig wordt beheerd, is het mogelijk om meerdere niveaus te krijgen die overeenkomen met dezelfde categorie (zoals "blauw", "Blauw" en "BLAUW"). In dergelijke gevallen geven velen er de voorkeur aan deze verschillen als tekens te beheren voordat ze worden omgezet in een factor (als de conversie überhaupt plaatsvindt).

In het tweede geval, als de gebruiker denkt dat ze met een tekenvector werkt, reageren bepaalde methoden mogelijk niet zoals verwacht. Dit basiskennis kan leiden tot verwarring en frustratie tijdens het debuggen van scripts en codes. Hoewel dit strikt genomen als de fout van de gebruiker kan worden beschouwd, vermijden de meeste gebruikers graag factoren te gebruiken en deze situaties helemaal te vermijden.

Basiscreatie van factoren

Factoren zijn een manier om categorische variabelen in R weer te geven. Een factor wordt intern opgeslagen als een vector van gehele getallen . De unieke elementen van de geleverde karaktervector staan bekend als de niveaus van de factor. Als de niveaus niet door de gebruiker worden geleverd, genereert R standaard de set unieke waarden in de vector, sorteert deze waarden alfanumeriek en gebruikt ze als niveaus.

 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"

Als u de volgorde van de niveaus wilt wijzigen, is er een optie om de niveaus handmatig op te geven:

levels(factor(charvar, levels = c("n","c")))

> levels(factor(charvar, levels = c("n","c")))
[1] "n" "c"

Factoren hebben een aantal eigenschappen. Aan niveaus kunnen bijvoorbeeld labels worden gegeven:

> f <- factor(charvar, levels=c("n", "c"), labels=c("Newt", "Capybara"))
> f
[1] Newt     Newt     Newt     Capybara Capybara Capybara
Levels: Newt Capybara

Een andere eigenschap die kan worden toegewezen, is of de factor is besteld:

> 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

Wanneer een droplevels() niet meer wordt gebruikt, kunt u deze neerzetten met de functie droplevels() :

> 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

Factorniveaus consolideren met een lijst

Er zijn tijden waarin het wenselijk is om factorniveaus in minder groepen te consolideren, misschien vanwege schaarse gegevens in een van de categorieën. Het kan ook voorkomen als u spelling of hoofdletters van de categorienamen hebt. Beschouw als een voorbeeld de factor

set.seed(1)
colorful <- sample(c("red", "Red", "RED", "blue", "Blue", "BLUE", "green", "gren"),
                   size = 20,
                   replace = TRUE)
colorful <- factor(colorful)

Omdat R hoofdlettergevoelig is, zou een frequentietabel van deze vector er als volgt uitzien.

table(colorful)
colorful  
blue  Blue  BLUE green  gren   red   Red   RED  
   3     1     4     2     4     1     3     2

Deze tabel geeft echter niet de werkelijke verdeling van de gegevens weer en de categorieën kunnen effectief worden teruggebracht tot drie soorten: Blauw, Groen en Rood. Er worden drie voorbeelden gegeven. De eerste illustreert wat een voor de hand liggende oplossing lijkt, maar geen oplossing zal bieden. De tweede geeft een werkende oplossing, maar is uitgebreid en rekenkundig duur. De derde is geen voor de hand liggende oplossing, maar is relatief compact en rekenkundig efficiënt.

Niveaus consolideren met 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

Merk op dat er dubbele niveaus zijn. We hebben nog steeds drie categorieën voor "Blauw", wat onze taak van het consolideren van niveaus niet voltooit. Bovendien is er een waarschuwing dat dubbele niveaus zijn verouderd, wat betekent dat deze code in de toekomst een fout kan genereren.

Niveaus consolideren met 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

Deze code genereert het gewenste resultaat, maar vereist het gebruik van geneste ifelse instructies. Hoewel er niets mis is met deze aanpak, kan het beheren van geneste ifelse verklaringen een vervelend karwei zijn en moet dit zorgvuldig worden gedaan.

Factorenniveaus consolideren met een lijst ( list_approach )

Een minder voor de hand liggende manier om niveaus te consolideren is om een lijst te gebruiken waarbij de naam van elk element de gewenste categorienaam is en het element een tekenvector is van de niveaus in de factor die moet worden toegewezen aan de gewenste categorie. Dit heeft als bijkomend voordeel dat direct aan het levels attribuut van de factor, zonder toe te wijzen nieuwe objecten.

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

Benchmarking van elke benadering

De tijd die nodig is om elk van deze benaderingen uit te voeren, wordt hieronder samengevat. (Omwille van de ruimte wordt de code om deze samenvatting te genereren niet getoond)

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

De ifelse loopt ongeveer twee keer zo snel als de ifelse benadering. Echter, behalve in tijden van zeer, zeer grote hoeveelheden gegevens, zullen de verschillen in uitvoeringstijd waarschijnlijk worden gemeten in microseconden of milliseconden. Met zulke kleine tijdsverschillen hoeft efficiëntie geen leidraad te zijn bij de beslissing welke aanpak te gebruiken. Gebruik in plaats daarvan een vertrouwde en comfortabele aanpak die u en uw medewerkers bij toekomstige beoordelingen zullen begrijpen.

Factoren

Factoren zijn een methode om categorische variabelen in R weer te geven. Gegeven een vector x waarvan de waarden kunnen worden geconverteerd naar tekens met behulp van as.character() , as.character() de standaardargumenten voor factor() en as.factor() een geheel getal toe aan elk afzonderlijk element van de vector evenals een niveaukenmerk en een labelkenmerk. Niveaus zijn de waarden x mogelijk kunnen worden gebruikt en labels kunnen het gegeven element zijn of worden bepaald door de gebruiker.

Om bijvoorbeeld te werken hoe factoren werken, maken we een factor met standaardattributen, vervolgens aangepaste niveaus en vervolgens aangepaste niveaus en labels.

# standard
factor(c(1,1,2,2,3,3))
[1] 1 1 2 2 3 3
Levels: 1 2 3

Er kunnen situaties optreden waarbij de gebruiker weet dat het aantal mogelijke waarden dat een factor kan aannemen groter is dan de huidige waarden in de vector. Hiervoor wijzen we de niveaus zelf in 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

Voor stijldoeleinden kan de gebruiker labels aan elk niveau toewijzen. Standaard zijn labels de karakterweergave van de niveaus. Hier wijzen we labels toe voor elk van de mogelijke niveaus in de factor.

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

Normaal kunnen factoren alleen worden vergeleken met == en != En als de factoren dezelfde niveaus hebben. De volgende vergelijking van factoren mislukt, hoewel ze gelijk lijken, omdat de factoren verschillende factorniveaus hebben.

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

Dit is logisch omdat de extra niveaus in de RHS betekenen dat R niet voldoende informatie over elke factor heeft om ze op een zinvolle manier te vergelijken.

De operatoren < , <= , > en >= zijn alleen bruikbaar voor geordende factoren. Deze kunnen categorische waarden vertegenwoordigen die nog steeds een lineaire volgorde hebben. Een geordende factor kan worden gemaakt door het argument ordered = TRUE aan de factor te geven of gewoon de ordered functie te gebruiken.

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

Zie de Factor-documentatie voor meer informatie.

Veranderende en herordenende factoren

Wanneer factoren worden gemaakt met standaardwaarden, worden levels gevormd door as.character toegepast op de ingangen en alfabetisch gerangschikt.

charvar <- rep(c("W", "n", "c"), times=c(17,20,14))
f <- factor(charvar)
levels(f)
# [1] "c" "n" "W"

In sommige situaties is de behandeling van de standaardvolgorde van levels (alfabetische / lexicale volgorde) acceptabel. Als je bijvoorbeeld gewoon de frequenties wilt plot , is dit het resultaat:

plot(f,col=1:length(levels(f)))

voer hier de afbeeldingsbeschrijving in

Maar als we een andere volgorde van levels , moeten we dit specificeren in de parameter levels of labels (zorg ervoor dat de betekenis van "bestelling" hier anders is dan geordende factoren, zie hieronder). Er zijn veel alternatieven om die taak te volbrengen, afhankelijk van de situatie.

1. Definieer de factor opnieuw

Wanneer het mogelijk is, kunnen we de factor opnieuw maken met behulp van de parameter levels in de gewenste volgorde.

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"

Wanneer de ingangsniveaus verschillen van het gewenste uitgangsniveaus, gebruiken we de labels parameter die veroorzaakt levels parameter om een "filter" aanvaardbare ingangswaarden worden, maar laat de eindwaarden van "niveaus" voor de factor vector als argument 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. Gebruik de relevel functie

Wanneer er één specifiek level dat het eerste moet zijn, kunnen we relevel . Dit gebeurt bijvoorbeeld in de context van statistische analyse, wanneer een base nodig is om de hypothese te testen.

g<-relevel(f, "n") # moves n to be the first level
levels(g)
# [1] "n" "c" "W"  

Zoals kan worden geverifieerd zijn f en g hetzelfde

all.equal(f, g)
# [1] "Attributes: < Component “levels”: 2 string mismatches >"
all.equal(f, g, check.attributes = F)
# [1] TRUE

3. Herordenende factoren

Er zijn gevallen waarin we de levels opnieuw moeten reorder levels basis van een getal, een gedeeltelijk resultaat, een berekende statistiek of eerdere berekeningen. Laten we opnieuw ordenen op basis van de frequenties van de levels

table(g)
# g
#  n  c  W 
# 20 14 17 

De reorder is generiek (zie help(reorder) ), maar heeft in dit verband nodig: x , in dit geval de factor; X , een numerieke waarde van dezelfde lengte als x ; en FUN , een functie die moet worden toegepast op X en wordt berekend door het niveau van de x , die de volgorde van de levels bepaalt, die standaard toeneemt. Het resultaat is dezelfde factor met de niveaus opnieuw geordend.

g.ord <- reorder(g,rep(1,length(g)), FUN=sum) #increasing
levels(g.ord)
# [1] "c" "W" "n"

Om de afnemende volgorde te krijgen, beschouwen we negatieve waarden ( -1 )

g.ord.d <- reorder(g,rep(-1,length(g)), FUN=sum)
levels(g.ord.d)
# [1] "n" "W" "c"

Opnieuw is de factor hetzelfde als de anderen.

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

Wanneer er een kwantitatieve variabele is gerelateerd aan de factorvariabele, kunnen we andere functies gebruiken om de levels opnieuw te ordenen. Laten we nemen de iris data ( help("iris") voor meer informatie), voor het herordenen van de Species factor met behulp van de gemiddelde 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"

De gebruikelijke boxplot (zeg: with(miris, boxplot(Petal.Width~Species) ) toont de species in deze volgorde: setosa , versicolor en virginica . Maar met behulp van de geordende factor krijgen we de soort geordend op de gemiddelde 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) 

voer hier de afbeeldingsbeschrijving in

Bovendien is het ook mogelijk om de namen van levels te wijzigen, ze in groepen te combineren of nieuwe levels toe te voegen. Daarvoor gebruiken we de functie van dezelfde 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 

- Geordende factoren

Ten slotte weten we dat ordered factoren verschillen van factors , de eerste wordt gebruikt om ordinale gegevens weer te geven en de tweede om te werken met nominale gegevens . In het begin heeft het geen zin om de volgorde van levels voor geordende factoren te wijzigen, maar we kunnen de labels wijzigen.

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

Opnieuw opbouwen van factoren vanaf nul

Probleem

Factoren worden gebruikt om variabelen voor te stellen die waarden uit een set categorieën aannemen, bekend als Niveaus in R. Een experiment kan bijvoorbeeld worden gekenmerkt door het energieniveau van een batterij, met vier niveaus: leeg, laag, normaal en vol. Vervolgens konden voor 5 verschillende bemonsteringslocaties die niveaus in die termen als volgt worden geïdentificeerd:

vol , vol , normaal , leeg , laag

Typisch, in databases of andere informatiebronnen, wordt de verwerking van deze gegevens door willekeurige gehele indices geassocieerd met de categorieën of niveaus. Als we aannemen dat we voor het gegeven voorbeeld de indices als volgt toewijzen: 1 = leeg, 2 = laag, 3 = normaal, 4 = vol, dan kunnen de 5 monsters worden gecodeerd als:

4 , 4 , 3 , 1 , 2

Het kan voorkomen dat u vanuit uw informatiebron, bijvoorbeeld een database, alleen de gecodeerde lijst met gehele getallen hebt en de catalogus die elk geheel getal aan elk niveau-trefwoord koppelt. Hoe kan een factor R uit die informatie worden gereconstrueerd?

Oplossing

We simuleren een vector van 20 gehele getallen die de monsters vertegenwoordigen, die elk een van vier verschillende waarden kunnen hebben:

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

De eerste stap is om een factor uit de vorige reeks te maken, waarbij de niveaus of categorieën exact de getallen van 1 tot 4 zijn.

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
Niveaus: 1 2 3 4

Nu moet je de factor die al is gemaakt aankleden met de index-tags:

levels(fii) <- c("empty", "low", "normal", "full")
fii

[1] volledig normaal volledig leeg leeg normaal laag normaal laag leeg
[11] normaal vol leeg laag vol leeg normaal leeg vol leeg
Niveaus: leeg laag normaal vol



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow