not - lasso in r
Extraer nombres de variables de coeficiente de glmnet en un data.frame (8)
Aquí, escribí un ejemplo reproducible y coloqué un ejemplo binario (logístico) usando cv.glmnet
. Un glmnet
modelo glmnet
también funcionará. Al final de este ejemplo, reuní los coeficientes distintos de cero y las características asociadas en un data.frame llamado myResults
:
library(glmnet)
X <- matrix(rnorm(100*10), 100, 10);
X[51:100, ] <- X[51:100, ] + 0.5; #artificially introduce difference in control cases
rownames(X) <- paste0("observation", 1:nrow(X));
colnames(X) <- paste0("feature", 1:ncol(X));
y <- factor( c(rep(1,50), rep(0,50)) ); #binary outcome class label
y
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [51] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## Levels: 0 1
## Perform logistic model fit:
fit1 <- cv.glmnet(X, y, family="binomial", nfolds=5, type.measure="auc"); #with K-fold cross validation
# fit1 <- glmnet(X, y, family="binomial") #without cross validation also works
## Adapted from @Mehrad Mahmoudian:
myCoefs <- coef(fit1, s="lambda.min");
myCoefs[which(myCoefs != 0 ) ] #coefficients: intercept included
## [1] 1.4945869 -0.6907010 -0.7578129 -1.1451275 -0.7494350 -0.3418030 -0.8012926 -0.6597648 -0.5555719
## [10] -1.1269725 -0.4375461
myCoefs@Dimnames[[1]][which(myCoefs != 0 ) ] #feature names: intercept included
## [1] "(Intercept)" "feature1" "feature2" "feature3" "feature4" "feature5" "feature6"
## [8] "feature7" "feature8" "feature9" "feature10"
## Asseble into a data.frame
myResults <- data.frame(
features = myCoefs@Dimnames[[1]][ which(myCoefs != 0 ) ], #intercept included
coefs = myCoefs [ which(myCoefs != 0 ) ] #intercept included
)
myResults
## features coefs
## 1 (Intercept) 1.4945869
## 2 feature1 -0.6907010
## 3 feature2 -0.7578129
## 4 feature3 -1.1451275
## 5 feature4 -0.7494350
## 6 feature5 -0.3418030
## 7 feature6 -0.8012926
## 8 feature7 -0.6597648
## 9 feature8 -0.5555719
## 10 feature9 -1.1269725
## 11 feature10 -0.4375461
Me gustaría extraer los coeficientes del modelo generado por glmnet y crear una consulta SQL a partir de ellos. La función coef(cv.glmnet.fit)
produce un objeto '' dgCMatrix
''. Cuando lo convierto a una matriz usando as.matrix
, los nombres de las variables se pierden y solo quedan los valores del coeficiente.
Sé que uno puede imprimir los coeficientes en la pantalla, sin embargo, ¿es posible escribir los nombres en un marco de datos?
¿Alguien puede ayudar a extraer estos nombres?
Hay un enfoque con el uso de coef () al objeto glmnet () (su modelo). En un caso debajo del índice [[1]], indique el número de clases de resultados en regresión logística multinomial, tal vez para otros modelos debería eliminarlo.
coef_names_GLMnet <- coef(GLMnet, s = 0)[[1]]
row.names(coef_names_GLMnet)[coef_names_GLMnet@i+1]
Los índices de row.names () en tal caso necesitan incrementarse (+1) porque la numeración de variables (características de datos) en el objeto coef () comienza desde 0, pero después de la transformación la numeración del vector de caracteres comienza desde 1.
Los nombres deben ser accesibles como dimnames(coef(cv.glmnet.fit))[[1]]
, por lo que los siguientes deben poner los nombres de los coeficientes y los valores en un data.frame: data.frame(coef.name = dimnames(coef(GLMNET))[[1]], coef.value = matrix(coef(GLMNET)))
Revise el paquete de la broom . Tiene una función tidy
que convierte la salida de diferentes objetos R (incluyendo glmnet
) en data.frames.
Sobre la base de la solución de Mehrad anterior, aquí hay una función simple para imprimir una tabla que contiene solo los coeficientes distintos de cero:
print_glmnet_coefs <- function(cvfit, s="lambda.min") {
ind <- which(coef(cvfit, s=s) != 0)
df <- data.frame(
feature=rownames(coef(cvfit, s=s))[ind],
coeficient=coef(cvfit, s=s)[ind]
)
kable(df)
}
La función anterior utiliza la función kable()
de knitr para producir una tabla lista para Markdown.
Suponiendo que sepa cómo obtener su lambda, encontré dos formas diferentes de mostrar los predictores necesarios en el modelo seleccionado para esa lambda en particular. Uno de ellos incluye el intercepto. La lambda se puede obtener mediante validación cruzada por medio de cv.glmnet de la biblioteca " glmnet ". Es posible que desee ver solo las últimas líneas de cada método:
myFittedLasso = glmnet(x=myXmatrix, y=myYresponse, family="binomial")
myCrossValidated = cv.glmnet(x=myXmatrix, y=myYresponse, family="binomial")
myLambda = myCrossValidated$lambda.1se # can be simply lambda
# Method 1 without the intercept
myBetas = myFittedLasso$beta[, which(myFittedLasso$lambda == myLambda)]
myBetas[myBetas != 0]
## myPredictor1 myPredictor2 myPredictor3
## 0.24289802 0.07561533 0.18299284
# Method 2 with the intercept
myCoefficients = coef(myFittedLasso, s=myLambda)
dimnames(myCoefficients)[[1]][which(myCoefficients != 0)]
## [1] "(Intercept)" "myPredictor1" "M_myPredictor2" "myPredictor3"
myCoefficients[which(myCoefficients != 0)]
## [1] -4.07805560 0.24289802 0.07561533 0.18299284
Tenga en cuenta que el ejemplo anterior implica una distribución binomial, pero los pasos se pueden aplicar a cualquier otro tipo.
ACTUALIZACIÓN: Los dos primeros comentarios de mi respuesta son correctos. He mantenido la respuesta debajo de la línea solo para la posteridad.
La siguiente respuesta es breve, funciona y no necesita ningún otro paquete:
tmp_coeffs <- coef(cv.glmnet.fit, s = "lambda.min")
data.frame(name = tmp_coeffs@Dimnames[[1]][tmp_coeffs@i + 1], coefficient = tmp_coeffs@x)
La razón para +1 es que el método @i indexa desde 0 para la intersección, pero @Dimnames [[1]] comienza en 1.
ANTIGUA RESPUESTA: (solo guardada para la posteridad) Pruebe estas líneas:
Los coeficientes distintos de cero:
coef(cv.glmnet.fit, s = "lambda.min")[which(coef(cv.glmnet.fit, s = "lambda.min") != 0)]
Las características que se seleccionan:
colnames(regression_data)[which(coef(cv.glmnet.fit, s = "lambda.min") != 0)]
Luego, unirlos como un marco de datos es un paso adelante, pero hágame saber si también desea esa parte del código.
# requires tibble.
tidy_coef <- function(x){
coef(x) %>%
matrix %>% # Coerce from sparse matrix to regular matrix.
data.frame %>% # Then dataframes.
rownames_to_column %>% # Add rownames as explicit variables.
setNames(c("term","estimate"))
}
Sin tibble:
tidy_coef2 <- function(x){
x <- coef(x)
data.frame(term=rownames(x),
estimate=matrix(x)[,1],
stringsAsFactors = FALSE)
}