2014-05-22 4 views
7

I fattori possono aiutare a prevenire alcuni tipi di errori di programmazione in R: non è possibile eseguire controlli di uguaglianza per fattori che utilizzano livelli diversi e si viene avvisati quando si eseguono controlli superiori/inferiori rispetto a fattori non ordinati.Unire in modo sicuro i frame di dati per colonne fattoriali

a <- factor(letters[1:3]) 
b <- factor(letters[1:3], levels=letters[4:1]) 
a == b 
## Error in Ops.factor(a, b) : level sets of factors are different 
a < a 
## [1] NA NA NA 
## Warning message: 
## In Ops.factor(a, a) : < not meaningful for factors 

Tuttavia, contrariamente alle mie aspettative, questo controllo non viene eseguito quando si unisce frame di dati:

ad <- data.frame(x=a, a=as.numeric(a)) 
bd <- data.frame(x=b, b=as.numeric(b)) 
merge(ad, bd) 
## x a b 
## 1 a 1 4 
## 2 b 2 3 
## 3 c 3 2 

Questi fattori sembrano semplicemente essere costretto a caratteri.

È disponibile una "unione sicura" da qualche parte per il controllo? Vedete ragioni specifiche per non fare questo controllo di default?

Esempio (caso di utilizzo della vita reale): Si supponga di due insiemi di dati spaziali con suddivisione molto simile ma non identica, ad esempio, nei comuni. I set di dati si riferiscono a punti leggermente diversi nel tempo e alcuni dei comuni si sono fusi in quel lasso di tempo. Ogni set di dati ha una colonna "ID comune", forse chiamata anche identicamente. Mentre la semantica di questa colonna è molto simile, non vorrei (accidentalmente) unire i set di dati su questa colonna di ID di comuni. Invece, costruisco una tabella di corrispondenza tra gli ID comuni "vecchi" e "nuovi". Se gli ID dei comuni sono codificati come fattori, una "unione sicura" darebbe un controllo di correttezza per l'operazione di unione senza costi aggiuntivi (di implementazione) e costi computazionali molto bassi.

+0

IIUC, preferiresti un errore in questo caso perché i livelli non corrispondono? – Arun

+0

@Arun: In molti casi d'uso preferirei un errore, o per lo meno un avvertimento. – krlmlr

+0

Capisco. Per curiosità, in che modo consideri questo non sicuro? – Arun

risposta

0

Bene, con molto credito (e scuse a) MrFlick:

> attributes(ad$x) 
$levels 
[1] "a" "b" "c" 

$class 
[1] "factor" 


> attributes(ad$a) 
NULL 

> attributes(ad$b) 
NULL 

> adfoo<-merge(ad,bd) 

> attributes(adfoo$x) 
$levels 
[1] "a" "b" "c" 

$class 
[1] "factor" 

Quindi, in realtà la colonna fusione $x è un fattore, anche se solo i livelli comuni ad entrambi ad e bd vengono uniti. Le altre colonne sono state costruite da molto tempo fa.

+0

Non vedo dove 'data.frame' sta rimuovendo l'attributo' factor' dai valori iniziali. Qual è la prova di ciò? – MrFlick

+0

@MrFlick prova a eseguire 'attributes (a)' e 'attributes (ad)'. Si prega di non scaricare i post senza prima indagare. –

+0

Non stavo scaricando; Ho investigato prima e per questo sono stato confuso. Ho confrontato gli attributi '(a)' e 'attributes (ad $ x)' che erano identici. Sono stato sorpreso di vederti guardare 'attributes (ad)'. Un 'data.frame' è solo una raccolta di vettori. Il 'data.frame' stesso non assume gli attributi di nessuna delle sue colonne né gli attributi() indagano in modo ricorsivo sui sottoelementi. Un 'data.frame' può contenere fattori con diversi livelli:' dd <-data.frame (x = letters [1: 2], y = letters [11:12]); levels (dd $ x); livelli (gg $ y) ' – MrFlick

1

La "guardia sicura" con merge è il parametro by=. Puoi impostare esattamente le colonne che ritieni debbano corrispondere. Se si abbinano colonne di due fattori, R utilizzerà le etichette di quei valori per abbinarle. Quindi "a" corrisponderà a "a" indipendentemente da come il funzionamento interno nascosto del fattore abbia codificato quei valori. Questo è ciò che vede un utente, quindi è così che verrà unito. È proprio come con i valori numerici, è possibile scegliere di unire colonne che hanno intervalli diversi completi (la prima colonna ha 1:10, la seconda ha 100: 1000). Quando è impostato il valore by, R farà ciò che viene richiesto. E se non si imposta esplicitamente il parametro by, allora R troverà tutti i nomi di colonna condivisa nei due data.frames e li userà.

E molte volte durante l'unione, non sempre si prevedono corrispondenze. A volte stai utilizzando all.x o all.y per ottenere in particolare record senza corrispondenza. In questo caso, a seconda di come sono stati creati i diversi data.frames, non è possibile conoscere i livelli che non ha. Quindi non è affatto irragionevole cercare di unirli.

Quindi in pratica R sta trattando fattori come i caratteri durante l'unione, perché suppone che tu sappia già che due colonne appartengono insieme.