2015-01-06 6 views
14

Я хотел бы извлечь коэффициенты модели, сгенерированные glmnet, и создать из них SQL-запрос. Функция coef(cv.glmnet.fit) дает объект 'dgCMatrix'. Когда я преобразовываю его в матрицу с помощью as.matrix, имена переменных теряются и остаются только значения коэффициентов.Извлечение имен переменных переменных из glmnet в data.frame

Я знаю, что можно напечатать коэффициенты на экране, однако можно ли записать имена в кадр данных?

Может ли кто-нибудь помочь в получении этих имен?

+0

Вам необходимо опубликовать воспроизводимый пример. Опубликуйте некоторые данные, сделайте пример, сообщите нам, в чем проблема и что вы хотели бы. Используя 'glmnet', я всегда получаю имена переменных по умолчанию, поэтому я не понимаю вопроса. – LyzandeR

ответ

2

Проверить broom упаковка. Он имеет функцию tidy, которая преобразует вывод различных R-объектов (включая glmnet) в data.frames.

10

ОБНОВЛЕНИЕ: Оба первых двух ответа на мой вопрос верны. Я сохранил ответ ниже строки только для потомков.

Следующий ответ короток, он работает и не нуждается в какой-либо другой пакет:

tmp_coeffs <- coef(cv.glmnet.fit, s = "lambda.min") 
data.frame(name = [email protected][[1]][[email protected] + 1], coefficient = [email protected]) 

Причиной +1 является то, что метод @i индексы от 0 для перехвата, но @Dimnames [[1 ]] начинается с 1.


OLD ОТВЕТ: (хранится только для потомков) Попробуйте эти строки:

ненулевым со efficients:

coef(cv.glmnet.fit, s = "lambda.min")[which(coef(cv.glmnet.fit, s = "lambda.min") != 0)] 

Признаки, которые выбраны:

colnames(regression_data)[which(coef(cv.glmnet.fit, s = "lambda.min") != 0)] 

Затем положить их вместе как dataframe является Staight вперед, но дайте мне знать, если вы хотите, что часть кода тоже.


+4

Обратите внимание, что 'colnames (regression_data) [which (coef (cv.glmnet.fit, s =" lambda.min ")! = 0)]' не учитывает перехват (первый столбец) и поэтому показывает неправильные имена – RUser4512

+2

Метод '@ x' объекта даст вам ненулевые коэффициенты. –

+0

Благодарим вас за ввод. Я теперь предоставил лучшее решение –

5

Имена должны быть доступны, как dimnames(coef(cv.glmnet.fit))[[1]], так что следующий должен поставить имена обоих коэффициентов и значений в data.frame: data.frame(coef.name = dimnames(coef(GLMNET))[[1]], coef.value = matrix(coef(GLMNET)))

3

Опираясь на решение Mehrad в выше, здесь простая функция напечатать таблицу, содержащую только ненулевые коэффициенты:

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) 
} 

функция выше использует функцию kable() от knitr для получения Markdown- готовый стол.

+0

's = 'lambda.min' дает мне ошибку. 'Ошибка в лямбда [1] - s: нечисловой аргумент для двоичного оператора. Любая идея? –

2

Существует подход с использованием коэфа() к glmnet() объекта (ваша модель). В приведенном ниже индексе индекс [[1]] указывает количество результатов в многолинейной логистической регрессии, возможно, для других моделей вы должны удалить его.

coef_names_GLMnet <- coef(GLMnet, s = 0)[[1]] 
row.names(coef_names_GLMnet)[[email protected]+1] 

ряд.имена() индексы в таком случае потребности приращением (+1), потому что нумерация переменных (признаков) данных в коэф() объекта от 0 главную страницу, но после того, как преобразование символов вектора нумерации, начинающихся с 1

2
# 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")) 
} 

Без Тиббл:

tidy_coef2 <- function(x){ 
    x <- coef(x) 
    data.frame(term=rownames(x), 
       estimate=matrix(x)[,1], 
       stringsAsFactors = FALSE) 
} 
2

Здесь я написал воспроизводимый пример и установлен двоичный (логистическая) пример использования cv.glmnet. A glmnet модель подходит также будет работать. В конце этого примера, я собрал ненулевые коэффициенты, а также связанные с ними функции, в data.frame называется 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 
[email protected][[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 = [email protected][[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 
+0

's = 'lambda.min' дает мне ошибку. 'Ошибка в лямбда [1] - s: нечисловой аргумент для двоичного оператора. Любая идея? –

+0

Вы использовали функцию 'glmnet' или' cv.glmnet'? Их результирующие структуры данных не совпадают. –

+0

'glmnet' ..' cv.glmnet' работал для меня .. спасибо! –

0

Предполагая, что вы знаете, как получить свой лямбда, я нашел два различных способа, чтобы показать предикторов, необходимых в выбранной модели для этой конкретной лямбда. Один из них включает перехват. Лямбда может быть получена с использованием кросс-валидации по среднему значению cv.glmnet от «glmnet». Вы можете смотреть только на последние строки для каждого метода:

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 

Обратите внимание, что в приведенном выше примере означает биномиальное распределение, но шаги могут быть применены к любому другому виду.

Смежные вопросы