2014-07-01 24 views
6

Ok a tutti, una volta per tutte, come si fa (enfasi su di te, perché sono sicuro che c'è più di un modo per ottenerlo) codice di contrasto (trattamento, somma, helmert, ecc.) e conservare un'etichetta fattoriale significativa (in modo da poter interpretare in modo significativo gli effetti) nella funzione glm?R - Come contrastare i fattori del codice e conservare le etichette significative nel sommario dell'output

Capisco che posso usare level() per capire quale livello di fattore è il riferimento, ma che diventa noioso quando comincio a coinvolgere fattori con 5 o 10 livelli e le loro interazioni.

Ecco un rapido esempio due fattore di ciò che intendo

outcome <- c(1,0,0,1,1,0,0,0,1, 0, 0, 1) 
firstvar <- c("A", "B", "C", "C", "B", "B", "A", "A", "C", "A", "C", "B") 
secondvar <- c("D", "D", "E", "F", "F", "E", "D", "E", "F", "F", "D", "E") 
df <- as.data.frame(cbind(outcome, firstvar, secondvar)) 

df$firstvar <- as.factor(df$firstvar) 
df$secondvar <- as.factor(df$secondvar) 

#not coded manually (and default appears to be dummy or treatment coding) 
#gives meaningful factor labels in summary function 
summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial")) 

#effects coded 
#does not give meaningful factor labels 
contrasts(df$firstvar)=contr.sum(3) 
contrasts(df$secondvar)=contr.sum(3) 
summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial")) 

#dummy coded 
contrasts(df$firstvar)=contr.treatment(3); 
contrasts(df$secondvar)=contr.treatment(3); 
summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial")) 

C'è ne e tutti i suggerimenti saranno apprezzati. Questo problema mi ha infastidito per un po 'e sono sicuro che esiste una soluzione semplice (ish).

risposta

4

Bene, la risposta semplice (per contr.treatment almeno), è che è necessario passare i livelli di fattore alla funzione, anziché solo il conteggio totale. Nella maggior parte dei casi questo imposterà correttamente i nomi dei livelli. Ad esempio

contr.treatment(levels(df$firstvar)) 

# B C 
# A 0 0 
# B 1 0 
# C 0 1 

e quindi R utilizza i nomi di colonna come etichette/suffissi sui coefficienti nel riepilogo di regressione. Tuttavia, anche durante il passaggio delle etichette, contr.sum non si desidera impostare i nomi delle colonne. Qui possiamo comunque creare il nostro wrapper.

named.contr.sum<-function(x, ...) { 
    if (is.factor(x)) { 
     x <- levels(x) 
    } else if (is.numeric(x) & length(x)==1L) { 
     stop("cannot create names with integer value. Pass factor levels") 
    } 
    x<-contr.sum(x, ...) 
    colnames(x) <- apply(x,2,function(x) 
     paste(names(x[x>0]), names(x[x<0]), sep="-") 
    ) 
    x 
} 

Qui stiamo fondamentalmente Chiamare CHIAMARE contr.sum e solo l'aggiunta di nomi di colonna al risultato (più controllo alcuni errori). È possibile eseguire questo con

named.contr.sum(levels(df$firstvar)) 

# A-C B-C 
# A 1 0 
# B 0 1 
# C -1 -1 

Ho deciso di usare "A-C" e "B-C", come le etichette, ma si potrebbe cambiare la situazione nel codice, se volete. Poi in esecuzione

contrasts(df$firstvar)=named.contr.sum(levels(df$firstvar)) 
contrasts(df$secondvar)=named.contr.sum(levels(df$secondvar)) 

summary(glm(outcome ~ firstvar*secondvar, data=df, family="binomial")) 

vi darà

chiamata:

glm(formula = outcome ~ firstvar * secondvar, family = "binomial", 
    data = df) 

Coefficients: 
          Estimate Std. Error z value Pr(>|z|) 
(Intercept)    -6.855e+00 5.023e+03 -0.001 0.999 
firstvarA-C    -6.855e+00 6.965e+03 -0.001 0.999 
firstvarB-C    6.855e+00 6.965e+03 0.001 0.999 
secondvarD-F    -6.855e+00 6.965e+03 -0.001 0.999 
secondvarE-F    -6.855e+00 6.965e+03 -0.001 0.999 
firstvarA-C:secondvarD-F 2.057e+01 8.473e+03 0.002 0.998 
firstvarB-C:secondvarD-F -1.371e+01 1.033e+04 -0.001 0.999 
firstvarA-C:secondvarE-F 7.072e-10 1.033e+04 0.000 1.000 
firstvarB-C:secondvarE-F 6.855e+00 8.473e+03 0.001 0.999 
+1

Grazie uomo! Quando dici che "hai deciso di usare" AC "e" BC "come etichette, dove l'hai chiamato nel codice? Sono abituato a usare relevel e rieseguire i miei contrasti per classificare il livello di riferimento. – gh0strider18

+0

Dovrei avere è stato più chiaro: è in 'paste (nomi (x [x> 0]), nomi (x [x <0]), sep =" - ")' linea. Io uso il rowname del valore con "1" meno il rowname con valore "-1". La pasta mette il "-" tra questi valori. – MrFlick