2010-11-25 2 views
9

При использовании формул с коэффициентами, приведенные модели обозначают коэффициенты XY, где X - это имя фактора, а Y - его конкретный уровень. Я хочу иметь возможность создать формулу из названий этих коэффициентов.Преобразование имен коэффициентов в формулу в R

Причина: Если я поместил лассо в разреженную матрицу дизайна (как я делаю ниже), я хотел бы создать новый объект формулы, который содержит только термины для ненулевых коэффициентов.

require("MatrixModels") 
require("glmnet") 
set.seed(1) 
n <- 200 
Z <- data.frame(letter=factor(sample(letters,n,replace=T),letters), 
       x=sample(1:20,200,replace=T)) 
f <- ~ letter + x:letter + I(x>5):letter 
X <- sparse.model.matrix(f, Z) 
beta <- matrix(rnorm(dim(X)[2],0,5),dim(X)[2],1) 
y <- X %*% beta + rnorm(n) 

myfit <- glmnet(X,as.vector(y),lambda=.05) 
fnew <- rownames(myfit$beta)[which(myfit$beta != 0)] 
[1] "letterb"    "letterc"    "lettere"    
[4] "letterf"    "letterg"    "letterh"    
[7] "letterj"    "letterm"    "lettern"    
[10] "lettero"    "letterp"    "letterr"    
[13] "letters"    "lettert"    "letteru"    
[16] "letterw"    "lettery"    "letterz"    
[19] "lettera:x"   "letterb:x"   "letterc:x"   
[22] "letterd:x"   "lettere:x"   "letterf:x"   
[25] "letterg:x"   "letterh:x"   "letteri:x"   
[28] "letterj:x"   "letterk:x"   "letterl:x"   
[31] "letterm:x"   "lettern:x"   "lettero:x"   
[34] "letterp:x"   "letterq:x"   "letterr:x"   
[37] "letters:x"   "lettert:x"   "letteru:x"   
[40] "letterv:x"   "letterw:x"   "letterx:x"   
[43] "lettery:x"   "letterz:x"   "letterb:I(x > 5)TRUE" 
[46] "letterc:I(x > 5)TRUE" "letterd:I(x > 5)TRUE" "lettere:I(x > 5)TRUE" 
[49] "letteri:I(x > 5)TRUE" "letterj:I(x > 5)TRUE" "letterl:I(x > 5)TRUE" 
[52] "letterm:I(x > 5)TRUE" "letterp:I(x > 5)TRUE" "letterq:I(x > 5)TRUE" 
[55] "letterr:I(x > 5)TRUE" "letteru:I(x > 5)TRUE" "letterv:I(x > 5)TRUE" 
[58] "letterx:I(x > 5)TRUE" "lettery:I(x > 5)TRUE" "letterz:I(x > 5)TRUE" 

Из этого я хотел бы иметь формулу

~ I(letter=="d") + I(letter=="e") + ...(etc) 

Я проверил формулу() и all.vars() безрезультатно. Кроме того, запись функции для синтаксического анализа это немного боль из-за различных типов терминов, которые могут возникнуть. Например, для x: letter, когда x является числовым значением, а буква - фактором, или I (x> 5): буква как другой раздражающий случай.

Так что я не знаю о какой-либо функции для преобразования между формулой и ее символьным представлением и обратно?

+0

Это не формула, которую я признаю в R – 2010-11-25 22:00:24

+1

Возможно, я неправильно понимаю, но вы, похоже, не полностью гребли формулы модели R. Вы не включаете в формулу XY биты, вы включаете X и `model.matrix()` и `model.frame()` делаете свою вещь, чтобы расширить уровни X до соответствующих столбцов матрицы модели, XY. – 2010-11-25 22:06:30

ответ

3

Когда я запускал код, у меня было что-то другое, поскольку set.seed() не был указан. Вместо того, чтобы использовать имя переменной «буква», я использовал «letter_» в качестве удобного расщепления маркера:

> fnew <- rownames(myfit$beta)[which(myfit$beta != 0)] 

> fnew 
[1] "letter_c" "letter_d" "letter_e" "letter_f" "letter_h" "letter_k" "letter_l" 
[8] "letter_o" "letter_q" "letter_r" "letter_s" "letter_t" "letter_u" "letter_v" 
[15] "letter_w" 

Затем сделал раскол и фасуют в матрицу символов:

> fnewmtx <- cbind(lapply(sapply(fnew, strsplit, split="_"), "[[", 2), 
+ lapply(sapply(fnew, strsplit, split="_"), "[[", 1)) 

fnewmtx [1] [2]
letter_c "с" "буквы" letter_d "D" "буквой" letter_e "е" "буквой" letter_f "е" "буквой" обрезала

остальное

И завернуты функции пасты, выводимые в as.formula(), что является половиной ответа на вопрос о том, как «преобразовать формулу и ее символьное представление и обратно». Другая половина as.character()

form <- as.formula(paste("~", 
      paste( 
       paste(" I(", fnewmtx[,2], "_ ==", "'",fnewmtx[,1],"') ", sep="") , 
      sep="", collapse="+") 
       ) 
      ) # edit: needed to add back the underscore 

И выход теперь соответствующий объект класса:

> class(form) 
[1] "formula" 
> form 
~I(letter_ == "c") + I(letter_ == "d") + I(letter_ == "e") + 
    I(letter_ == "f") + I(letter_ == "h") + I(letter_ == "k") + 
    I(letter_ == "l") + I(letter_ == "o") + I(letter_ == "q") + 
    I(letter_ == "r") + I(letter_ == "s") + I(letter_ == "t") + 
    I(letter_ == "u") + I(letter_ == "v") + I(letter_ == "w") 

Я нахожу интересным, что преобразование as.formula сделал одинарные кавычки вокруг буквы в двойные кавычки.

Редактировать: Теперь, когда проблема имеет дополнительное измерение или два, мое предложение состоит в том, чтобы пропустить воссоздание формулы. Обратите внимание, что rownames из myfit $ бета точно так же, как имена столбцов X, поэтому вместо того, чтобы использовать ненулевые rownames в качестве индексов для выбора столбцов в X матрицы:

> str(X[ , which(colnames(X) %in% rownames(myfit$beta)[which(myfit$beta != 0)])]) 
Formal class 'dgCMatrix' [package "Matrix"] with 6 slots 
    [email protected] i  : int [1:429] 9 54 91 157 166 37 55 68 117 131 ... 
    [email protected] p  : int [1:61] 0 5 13 20 28 36 42 50 60 68 ... 
    [email protected] Dim  : int [1:2] 200 60 
    [email protected] Dimnames:List of 2 
    .. ..$ : chr [1:200] "1" "2" "3" "4" ... 
    .. ..$ : chr [1:60] "letter_b" "letter_c" "letter_e" "letter_f" ... 
    [email protected] x  : num [1:429] 1 1 1 1 1 1 1 1 1 1 ... 
    [email protected] factors : list() 

> myfit2 <- glmnet(X[ , which(colnames(X) %in% rownames(myfit$beta)[which(myfit$beta != 0)])] ,as.vector(y),lambda=.05) 
> myfit2 

Call: glmnet(x = X[, which(colnames(X) %in% rownames(myfit$beta)[ 
              which(myfit$beta != 0)])], 
       y = as.vector(y), lambda = 0.05) 

    Df %Dev Lambda 
[1,] 60 0.9996 0.05 
2

Кристофера, что вы просите для появляется, после некоторого рассмотрения и изучения sparse.model.matrix и т. д., чтобы быть в некоторой степени вовлечен. Вы не объясняете , почему вы не хотите формировать полную разрешенную модельную матрицу для X_test, поэтому вам трудно сообщить, какой путь вперед, кроме двух вариантов ниже.

Если у вас есть большое количество наблюдений в X_test и, следовательно, не хотите производить полную разреженную матрицу для использования в predict() для вычислительных причин, это может быть более целесообразным разделить X_test на два или более куски образцов и формы разреженные матрицы моделей для каждого, в свою очередь, отбрасывая его после использования.

В противном случае вам необходимо будет подробно изучить код из пакета Matrix. Начните с sparse.model.matrix и обратите внимание, что затем он вызывает Matrix:::model.spmatrix и находит вызовы в Matrix:::fac2Sparse в этой функции. Возможно, вам понадобится кооптировать код из этих функций, но используйте модифицированный fac2Sparse для достижения того, чего вы хотите достичь.

Извините, я не могу предоставить готовый скрипт для этого, но это существенная задача кодирования. Если вы спуститесь по этому маршруту, ознакомьтесь с виньеткой Sparse Model Matrix в пакете Matrix и получите источники пакетов (из CRAN), чтобы узнать, описаны ли функции, о которых я упоминаю, в исходном коде (нет файлов Rd для fac2Sparse например). Вы также можете попросить авторов Матрицы (Martin Maechler и Doug Bates) за советом, хотя обратите внимание, что оба этих парня имели особенно тяжелую учебную нагрузку на этот срок.

Удачи вам!

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