Ricerca…


Sintassi

  1. fattore (x = carattere (), livelli, etichette = livelli, exclude = NA, ordinato = is.ordered (x), nmax = NA)
  2. Esegui ?factor o consultare la documentazione online.

Osservazioni

Un oggetto con factor classe è un vettore con un particolare insieme di caratteristiche.

  1. È memorizzato internamente come vettore integer .
  2. Mantiene un attributo levels mostra la rappresentazione dei caratteri dei valori.
  3. La sua classe è memorizzata come factor

Per illustrare, generiamo un vettore di 1.000 osservazioni da un insieme di colori.

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

Possiamo osservare ognuna delle caratteristiche del Color sopra elencate:

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

Il vantaggio principale di un oggetto fattore è l'efficienza nella memorizzazione dei dati. Un numero intero richiede meno memoria da memorizzare rispetto a un personaggio. Tale efficienza era altamente auspicabile quando molti computer avevano risorse molto più limitate rispetto alle macchine attuali (per una storia più dettagliata delle motivazioni alla base dell'utilizzo di fattori, vedere stringsAsFactors : una biografia non autorizzata ). La differenza nell'uso della memoria può essere vista anche nel nostro oggetto Color . Come puoi vedere, la memorizzazione di Color come carattere richiede circa 1,7 volte la quantità di memoria dell'oggetto Fattore.

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

Mappare l'intero al livello

Mentre il calcolo interno dei fattori vede l'oggetto come un numero intero, la rappresentazione desiderata per il consumo umano è il livello del personaggio. Per esempio,

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

è più facile per la comprensione umana di

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

Un'illustrazione approssimativa di come R sta facendo corrispondere la rappresentazione del carattere al valore intero interno è:

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

Confronta questi risultati con

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

Uso moderno dei fattori

Nel 2007, R ha introdotto un metodo di hashing per i personaggi riducendo il carico di memoria dei vettori di caratteri (ref: stringsAsFactors : una biografia non autorizzata ). Prendi nota del fatto che quando abbiamo stabilito che i personaggi richiedono 1,7 volte più spazio di archiviazione rispetto ai fattori, questo è stato calcolato in una versione recente di R, il che significa che l'utilizzo della memoria dei vettori di caratteri era ancora più faticoso prima del 2007.

Grazie al metodo dell'hash nella moderna R e alle risorse di memoria di gran lunga maggiori nei computer moderni, il problema dell'efficienza della memoria nell'archiviazione dei valori dei caratteri è stato ridotto a una preoccupazione molto piccola. L'atteggiamento prevalente nella comunità R è una preferenza per i vettori di carattere rispetto ai fattori nella maggior parte delle situazioni. Le cause primarie dello spostamento dai fattori sono

  1. L'aumento di dati di carattere non strutturati e / o vagamente controllati
  2. La tendenza dei fattori a non comportarsi come desiderato quando l'utente dimentica di avere a che fare con un fattore e non con un personaggio

Nel primo caso, non ha senso archiviare testo libero o campi di risposta aperti come fattori, poiché è improbabile che vi sia un modello che consenta più di un'osservazione per livello. In alternativa, se la struttura dei dati non è controllata con attenzione, è possibile ottenere più livelli che corrispondono alla stessa categoria (come "blu", "Blu" e "BLU"). In questi casi, molti preferiscono gestire queste discrepanze come caratteri prima di convertirli in un fattore (se la conversione avviene del tutto).

Nel secondo caso, se l'utente pensa che stia lavorando con un vettore di caratteri, alcuni metodi potrebbero non rispondere come previsto. Questa comprensione di base può portare a confusione e frustrazione durante il tentativo di eseguire il debug di script e codici. Mentre, a rigor di termini, questo può essere considerato un errore dell'utente, la maggior parte degli utenti è felice di evitare l'uso di fattori ed evitare del tutto queste situazioni.

Creazione di base di fattori

I fattori sono un modo per rappresentare le variabili categoriali in R. Un fattore è memorizzato internamente come vettore di numeri interi . Gli elementi unici del vettore dei caratteri forniti sono noti come livelli del fattore. Per impostazione predefinita, se i livelli non vengono forniti dall'utente, R genererà l'insieme di valori univoci nel vettore, ordinerà questi valori alfanumerico e li utilizzerà come livelli.

 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"

Se si desidera modificare l'ordinamento dei livelli, quindi un'opzione per specificare manualmente i livelli:

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

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

I fattori hanno un numero di proprietà. Ad esempio, i livelli possono essere indicati con etichette:

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

Un'altra proprietà che può essere assegnata è se il fattore è ordinato:

> 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

Quando un livello del fattore non viene più utilizzato, puoi rilasciarlo usando la funzione 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

Consolidamento dei livelli dei fattori con un elenco

Ci sono momenti in cui è auspicabile consolidare i livelli dei fattori in un numero inferiore di gruppi, forse a causa di dati sparsi in una delle categorie. Può anche verificarsi quando si hanno diverse grafie o lettere maiuscole dei nomi delle categorie. Considerare come un esempio il fattore

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

Poiché R è sensibile al maiuscolo / minuscolo, una tabella di frequenza di questo vettore appare come sotto.

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

Questa tabella, tuttavia, non rappresenta la vera distribuzione dei dati e le categorie possono essere effettivamente ridotte a tre tipi: blu, verde e rosso. Sono forniti tre esempi. Il primo illustra quella che sembra una soluzione ovvia, ma in realtà non fornisce una soluzione. Il secondo fornisce una soluzione funzionante, ma è prolisso e computazionalmente costoso. Il terzo non è una soluzione ovvia, ma è relativamente compatto e efficiente dal punto di vista computazionale.

Consolidare i livelli usando 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

Si noti che ci sono livelli duplicati. Abbiamo ancora tre categorie per "Blue", che non completa il nostro compito di consolidare i livelli. Inoltre, vi è un avviso che i livelli duplicati sono deprecati, il che significa che questo codice potrebbe generare un errore in futuro.

Consolidare i livelli usando 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

Questo codice genera il risultato desiderato, ma richiede l'uso di istruzioni ifelse annidate. Sebbene non vi sia nulla di sbagliato in questo approccio, la gestione ifelse dichiarazioni nidificate di ifelse può essere un compito noioso e deve essere fatto con attenzione.

Consolidamento dei livelli dei fattori con un elenco ( list_approach )

Un modo meno ovvio per consolidare i livelli consiste nell'utilizzare una lista in cui il nome di ciascun elemento è il nome della categoria desiderata e l'elemento è un vettore di caratteri dei livelli nel fattore che deve corrispondere alla categoria desiderata. Questo ha il vantaggio di lavorare direttamente sull'attributo dei levels del fattore, senza dover assegnare nuovi oggetti.

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 di ciascun approccio

Il tempo richiesto per eseguire ciascuno di questi approcci è riassunto di seguito. (Per motivi di spazio, il codice per generare questo sommario non viene mostrato)

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

L'approccio lista funziona all'incirca il doppio dell'approccio ifelse . Tuttavia, tranne che in tempi di quantità di dati molto grandi, le differenze nel tempo di esecuzione saranno probabilmente misurate in microsecondi o millisecondi. Con differenze di tempo così piccole, l'efficienza non deve guidare la decisione di quale approccio utilizzare. Invece, usa un approccio familiare e confortevole, che tu e i tuoi collaboratori comprenderete in futuro.

fattori

I fattori sono un metodo per rappresentare le variabili categoriali in R. Dato un vettore x cui valori possono essere convertiti in caratteri usando as.character() , gli argomenti predefiniti per factor() e as.factor() assegnano un intero a ciascun elemento distinto di il vettore, nonché un attributo di livello e un attributo di etichetta. I livelli sono i valori che x può assumere e le etichette possono essere l'elemento dato o determinato dall'utente.

Ad esempio, come funzionano i fattori creeremo un fattore con attributi predefiniti, quindi livelli personalizzati e quindi livelli ed etichette personalizzati.

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

Le istanze possono sorgere dove l'utente conosce il numero di valori possibili che un fattore può assumere è maggiore rispetto ai valori correnti nel vettore. Per questo assegniamo noi stessi i livelli 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

Per motivi di stile, l'utente potrebbe voler assegnare etichette a ciascun livello. Per impostazione predefinita, le etichette sono la rappresentazione dei caratteri dei livelli. Qui assegniamo etichette per ciascuno dei possibili livelli nel fattore.

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

Normalmente, i fattori possono essere confrontati solo usando == e != E se i fattori hanno gli stessi livelli. Il seguente confronto di fattori non riesce, anche se appaiono uguali perché i fattori hanno diversi livelli di fattore.

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

Questo ha senso poiché i livelli extra nel RHS significano che R non ha abbastanza informazioni su ciascun fattore per confrontarli in modo significativo.

Gli operatori < , <= , > e >= sono utilizzabili solo per i fattori ordinati. Questi possono rappresentare valori categoriali che hanno ancora un ordine lineare. Un fattore ordinato può essere creato fornendo l'argomento ordered = TRUE alla funzione factor o semplicemente usando la funzione ordered .

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

Per ulteriori informazioni, consultare la documentazione del Fattore .

Modifica e riordino dei fattori

Quando i fattori vengono creati con valori predefiniti, i levels sono formati da as.character applicati agli input e ordinati alfabeticamente.

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

In alcune situazioni il trattamento dell'ordine di levels di default (ordine alfabetico / lessicale) sarà accettabile. Ad esempio, se si è interessati a plot le frequenze, questo sarà il risultato:

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

inserisci la descrizione dell'immagine qui

Ma se vogliamo un diverso ordinamento di levels , dobbiamo specificare questo nei parametri levels o labels (facendo attenzione che il significato di "ordine" qui sia diverso dai fattori ordinati , vedi sotto). Ci sono molte alternative per svolgere questo compito a seconda della situazione.

1. Ridefinire il fattore

Quando è possibile, possiamo ricreare il fattore usando il parametro dei levels con l'ordine che vogliamo.

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"

Quando i livelli di input sono diversi dai livelli di output desiderati, utilizziamo il parametro labels che fa sì che il parametro levels diventi un "filtro" per valori di input accettabili, ma lascia i valori finali di "livelli" per il vettore fattore come argomento per 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. Utilizzare la funzione relevel

Quando c'è un level specifico che deve essere il primo, possiamo usare relevel . Ciò accade, ad esempio, nel contesto dell'analisi statistica, quando una categoria di base è necessaria per verificare l'ipotesi.

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

Come si può verificare f e g sono gli stessi

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

3. Fattori di riordino

Ci sono casi in cui è necessario reorder i levels base a un numero, un risultato parziale, una statistica calcolata o calcoli precedenti. Riordina in base alle frequenze dei levels

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

La funzione di reorder è generica (vedi help(reorder) ), ma in questo contesto ha bisogno di: x , in questo caso il fattore; X , un valore numerico della stessa lunghezza di x ; e FUN , una funzione da applicare a X e calcolata per livello della x , che determina l'ordine dei levels , per impostazione predefinita crescente. Il risultato è lo stesso fattore con i suoi livelli riordinati.

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

Per ottenere un ordine decrescente consideriamo valori negativi ( -1 )

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

Di nuovo il fattore è lo stesso degli altri.

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

Quando c'è una variabile quantitativa correlata alla variabile fattore, potremmo usare altre funzioni per riordinare i levels . Consente di prendere i dati iris ( help("iris") per ulteriori informazioni), per riordinare il fattore Species usando la sua media 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"

Il consueto boxplot (diciamo: with(miris, boxplot(Petal.Width~Species) ) mostrerà le parti in quest'ordine: setosa , versicolor e virginica, ma usando il fattore ordinato otteniamo la specie ordinata per la sua media 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) 

inserisci la descrizione dell'immagine qui

Inoltre, è anche possibile modificare i nomi dei levels , combinarli in gruppi o aggiungere nuovi levels . Per questo usiamo la funzione degli stessi levels nome.

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 

- Fattori ordinati

Infine, sappiamo che i fattori ordered sono diversi dai factors , il primo è utilizzato per rappresentare i dati ordinali e il secondo per lavorare con i dati nominali . All'inizio, non ha senso cambiare l'ordine dei levels per i fattori ordinati, ma possiamo cambiare le sue 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

Ricostruzione di fattori da zero

Problema

I fattori sono usati per rappresentare variabili che prendono valori da un insieme di categorie, conosciute come Livelli in R. Ad esempio, alcuni esperimenti potrebbero essere caratterizzati dal livello di energia di una batteria, con quattro livelli: vuoto, basso, normale e pieno. Quindi, per 5 diversi siti di campionamento, tali livelli potrebbero essere identificati, in questi termini, come segue:

pieno , pieno , normale , vuoto , basso

In genere, in database o altre fonti di informazioni, la gestione di questi dati avviene mediante indici interi arbitrari associati alle categorie o ai livelli. Se assumiamo che, per l'esempio dato, assegneremo gli indici come segue: 1 = vuoto, 2 = basso, 3 = normale, 4 = pieno, quindi i 5 campioni potrebbero essere codificati come:

4 , 4 , 3 , 1 , 2

Potrebbe capitare che, dalla tua fonte di informazioni, ad esempio un database, hai solo l'elenco codificato di numeri interi e il catalogo che associa ogni intero con ogni parola chiave di livello. Come può essere ricostruito un fattore di R da quella informazione?

Soluzione

Simuleremo un vettore di 20 numeri interi che rappresentano i campioni, ognuno dei quali può avere uno dei quattro valori diversi:

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

Il primo passo è creare un fattore, dalla sequenza precedente, in cui i livelli o le categorie sono esattamente i numeri da 1 a 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
Livelli: 1 2 3 4

Ora semplicemente, devi vestire il fattore già creato con i tag di indice:

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

[1] pieno normale pieno vuoto vuoto normale basso normale basso vuoto
[11] normale pieno vuoto basso pieno vuoto normale vuoto pieno vuoto
Livelli: vuoto basso normale pieno



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow