web-dev-qa-db-ja.com

glmnetからdata.frameに係数変数名を抽出する

Glmnetで生成されたモデル係数を抽出し、それらからSQLクエリを作成したいと思います。関数coef(cv.glmnet.fit)は 'dgCMatrix'オブジェクトを生成します。 as.matrixを使用して行列に変換すると、変数名が失われ、係数値のみが残されます。

画面に係数を印刷できることは知っていますが、データフレームに名前を書き込むことは可能ですか?

誰もがこれらの名前を抽出するのを助けることができますか?

25
David Eborall

PDATE:私の答えの最初の2つのコメントは両方とも正しいです。私は後世のために答えを線の下に置いた。

次の答えは短く、機能し、他のパッケージは必要ありません。

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

+1の理由は、@iメソッドは、切片に対して0からインデックスを作成しますが、@Dimnames[[1]]は1から始まります。


古い回答:(後世のためにのみ保持) これらの行を試してください:

非ゼロ係数:

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

その後、それらをデータフレームとしてまとめるのは簡単ですが、コードのその部分も必要な場合はお知らせください。


23

名前はdimnames(coef(cv.glmnet.fit))[[1]]としてアクセスできる必要があるため、以下は係数名と値の両方をdata.frameに入れる必要があります。data.frame(coef.name = dimnames(coef(GLMNET))[[1]], coef.value = matrix(coef(GLMNET)))

6
Peter

broom packageを確認してください。異なるRオブジェクト(tidyを含む)の出力をdata.framesに変換するglmnet関数があります。

4
Tim

上記の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)
}
_

上記の関数は、knitrのkable()関数を使用して、Markdown対応テーブルを作成します。

4
Keith Hughitt
# 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
Michael Rice

ここでは、再現可能な例を作成し、cv.glmnetを使用してバイナリ(ロジスティック)の例を適合させました。 glmnetモデル近似も機能します。この例の最後で、非ゼロの係数と関連する機能をmyResultsというdata.frameに組み立てました。

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
2
David C.

coef() to glmnet() object(ご使用のモデル)を使用するアプローチがあります。以下の場合、インデックス[[1]]は多項ロジスティック回帰の結果クラスの数を示します。他のモデルの場合は削除する必要があります。

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

row.names()このような場合、インデックスは増分する必要があります(+1)coef()の変数の列挙(オブジェクトは0から始まるが、変換文字の後) 1から始まるベクトルの数え上げ.

2
Bem Ostap

ラムダを取得する方法を知っていると仮定して、その特定のラムダの選択モデルで必要な予測子を表示する2つの異なる方法を見つけました。それらの1つにインターセプトが含まれます。ラムダは、「glmnet」ライブラリからcv.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

上記の例は二項分布を示していますが、ステップは他の種類に適用できることに注意してください。

1