R Language
fattori
Ricerca…
Sintassi
- fattore (x = carattere (), livelli, etichette = livelli, exclude = NA, ordinato = is.ordered (x), nmax = NA)
- Esegui
?factor
o consultare la documentazione online.
Osservazioni
Un oggetto con factor
classe è un vettore con un particolare insieme di caratteristiche.
- È memorizzato internamente come vettore
integer
. - Mantiene un attributo
levels
mostra la rappresentazione dei caratteri dei valori. - 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
- L'aumento di dati di carattere non strutturati e / o vagamente controllati
- 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)))
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)
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