2016-03-21 1 views
1

J'ai écrit une fonction pour prendre les coefficients d'un modèle (linéaire) et les appliquer sur les variables d'origine pour donner une trame de données de termes qui, lorsqu'ils sont additionnés, sera équivalente au résultat de predict(). Cette capacité me semble utile pour mieux comprendre l'influence de chaque variable (ou plus complexe terme d'interaction, etc) sur le modèle.R: appliquer les coefficients du modèle à travers les variables dans le modèle, une meilleure façon?

Y a-t-il un meilleur moyen? Je me sens comme un hack. J'ai regardé dans le str() des modèles, et ne vois pas une solution plus simple pour le moment. Tricky partie est d'attraper et d'appliquer des termes d'interaction.

library(plyr) 
nospredict = function(model, data = model$model, sorted = TRUE) { # model is model (from lm, glm...), data is data.frame to be applied to                  
    c = coef(model) # model must support coef()                                        
    my.names = names(c) = gsub(':', '*', names(c)) # ':' equals multiplication in formulas, coefs                           
    data = data[ , colnames(data) %in% my.names] # don't do the attach() below with a zillion variables...                          
    final.out = adply(data, 1, function(y) { # did I mention I like plyr?                                  
     attach(as.list(y), warn.conflicts = FALSE) # so you can do eval algebra blackRmagic                             
     out = ldply(my.names, function (x) { # did I mention...                                    
      Intercept = 1 # (Intercept) from model is a constant, multiply it by 1                               
      eval( parse( text = paste(c[x], "*", x) ) )  }) # blackRmagic                               
     out = as.data.frame(t(out)) ; colnames(out) = my.names ; out 
    }) 
    rownames(final.out) = rownames(data) 
    final.out$Predict = predict(model, data) ## add predict() as column                                  
    if (sorted) { 
     final.out[order(final.out$Predict), ] ## return df sorted by predict()                                
    } 
    final.out 
} 
set.seed(10538) 
df = data.frame(a = 1:10, b = rnorm(10), c = 1:10 + rnorm(10)) 
lmf = lm(c ~ a * b, data = df) 

> df 
a   b   c 
1 1 -0.41184664 1.3739709 
2 2 1.06464586 0.8975101 
3 3 -0.07522363 3.4910425 
4 4 1.21643049 2.8856876 
5 5 0.34061917 4.3851439 
6 6 -1.00020786 6.1836535 
7 7 -0.36954963 6.4734150 
8 8 -1.47754640 6.8150569 
9 9 -0.19312147 9.6432687 
10 10 2.32220098 9.4276813 


> nospredict(lmf) 
(Intercept)   a   b   a*b Predict 
1 0.09801818 0.9282185 0.48332671 -0.05438652 1.4551769 
2 0.09801818 1.8564370 -1.24942570 0.28118420 0.9862137 
3 0.09801818 2.7846555 0.08827944 -0.02980103 2.9411521 
4 0.09801818 3.7128740 -1.42755405 0.64254425 3.0258824 
5 0.09801818 4.6410925 -0.39973700 0.22490279 4.5642765 
6 0.09801818 5.5693110 1.17380385 -0.79249635 6.0486367 
7 0.09801818 6.4975295 0.43368863 -0.34160685 6.6876294 
8 0.09801818 7.4257480 1.73398922 -1.56094237 7.6968130 
9 0.09801818 8.3539665 0.22663962 -0.22952439 8.4490999 
10 0.09801818 9.2821850 -2.72524198 3.06658890 9.7215501 
+0

sort final par predict() valeurs ne fonctionnant pas ici, correction triviale, pas important pour la question. –

+0

Bien sûr, l'exemple reproductible ci-dessus n'est que cela. Je suis à la recherche d'une solution qui soit généralisable sur la plupart ou toutes les formules de modèles (sans savoir que le modèle avait «a» et «b» dedans, etc.). –

Répondre

1
junk <- data.frame(x1 = rnorm(100), x2 = rnorm(100)) 

junk$YY <- 2 * junk$x1 + 4 * junk$x2 + 6 * junk$x1 * junk$x2 + 7 + rnorm(100) 

out <- lm(YY ~ x1 * x2, data = junk, x = TRUE) # The x = TRUE part is key! 

head(out$x) 
    (Intercept)   x1   x2  x1:x2 
1   1 -0.34885894 -0.8127228 0.283525629 
2   1 -0.04482498 -0.1601600 0.007179167 
3   1 -1.11721391 0.3266213 -0.364905892 
4   1 -0.08530188 0.3482372 -0.029705287 
5   1 0.19138684 -0.1659683 -0.031764149 
6   1 -1.89493717 1.0261454 -1.944481020 

coef(out) 
(Intercept)   x1   x2  x1:x2 
    7.053434 1.804441 4.130249 5.970553 

nomThings <- t(t(out$x[, names(coef(out))]) * coef(out)) 

Je ne suis pas tout à fait sûr que cela fonctionnera correctement si vous avez des facteurs comme variables indépendantes, ou qu'il fonctionne correctement dans toutes les situations. Mais je le soupçonne.

Vous pouvez, bien sûr, enregistrer coef (out) comme objet temporaire, et ainsi de suite, pour rendre le code un peu plus lisible et légèrement plus efficace. Étant donné que vous pouvez facilement faire cela, je réfléchirais sérieusement à savoir si vous devriez le faire.

+0

Merci. x = TRUE dans l'appel lm() est l'option magique qui fournit une matrice de modèle complète et rend la vie beaucoup plus facile et probablement plus fiable. Indépendant de la valeur de faire cela, bien sûr. –