2010-11-25 18 views
9

numaralı formüle dönüştürme Formüle sahip olan formülleri kullanırken, takılan modeller XY katsayılarını belirtir, burada X, faktörün adıdır ve Y belirli bir düzeydir. Bu katsayıların isimlerinden bir formül oluşturabilmek istiyorum.Katsayı adlarını R

Nedeni: Bir kementin bir tasarım matrisine sığması durumunda (aşağıda yaptığım gibi), yalnızca sıfır olmayan katsayılar için terimler içeren yeni bir formül nesnesi oluşturmak istiyorum. Bundan

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" 

ben boşuna formülü() ve all.vars() teslim

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

bir formüle sahip istiyoruz. Ayrıca, bunu ayrıştırmak için bir işlev yazmak, ortaya çıkabilecek farklı terimlerden dolayı bir parça acıdır. Örneğin, x için: sayısal bir değer olduğunda harf ve harf bir faktör veya I (x> 5): başka bir can sıkıcı durum olarak mektup.

Bu yüzden formül ve karakter gösterimi arasında dönüştürme ve geri dönüş için bazı işlevlerden haberdar değilim?

+0

Bu tanıdığım bir formül değil. R –

+1

Belki de yanlış anlıyorum, ancak R'nin model formüllerini tam olarak göremiyorsunuz. Formülü XY bitlerine dahil etmiyorsunuz, X ve 'model.matrix()' ve 'model.frame()' yi dahil ediyorsunuz, X'in seviyelerini ilgili model matris sütunlarına genişletmek için XY. –

+0

Formülü neden istediğinizi açıklar mısınız? Son kullanım nedir? –

cevap

3

Kodu çalıştırdığımda, set.seed() belirtilmemiş olduğundan biraz farklı bir şey aldım.

> 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" 

Sonra bölünmüş yaptı ve bir karakter matris içine paketlenmiş:

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

fnewmtx yerine değişken adı "harfi" kullanmak yerine, ben uygun bir bölme işareti olarak "letter_" kullanılmış [1] [2] f " "harfi" "letter_f " "c" "harfi" letter_d, "d", "harfi" letter_e "e"" harfi letter_c
kalan

snipped

Ve "formül ve karakter gösterimi arasında dönüştürme ve geri dönüş" nasıl yanıtın yarısı olan macun işlev (ler) in.formula() içinde çıktı. Diğer yarısı()

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

as.character Ve çıkış şimdi uygun bir sınıf nesnesidir:

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

Ben as.formula dönüşüm etrafında tek tırnak yapılan ilginç bulmak çift ​​tırnak içine harfler.

Düzenleme: Artık sorunun ek bir iki boyutu var, benim önerim formülün rekreasyonunu atlamak. myfit $ beta rownames tam X'in sütun adları aynı olduğunu unutmayın, bu nedenle endeksleri X matrisi içinde sütunları seçmek üzere yerine sıfır olmayan rownames kullanın:

> 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 
+0

Teşekkürler DWin! Bu yakın, ama genel bir çözüm değil. Örneğimi güncelledim. Çözümünüzü uzatan hızlı bir düzeltme var mı? –

+0

Ayrıca, fnewmtx oluştururken, strsplit, split = "" yerine split = "_" kullanılmasın mı? –

+0

Oldukça doğru. Ben düzenleyeceğim Bir etkileşim formülünün karmaşıklığı ile başa çıkabilir miyim, ancak bunun üzerine hızlı bir cevap beklemiyor muyum ..... güncelleme: düzenlemeye çalıştım ama alt çizgi, orijinalin kod bölümlerinde ve görüntülenmiyor SO sayfasında. Re- "kodlu" ve belki de şimdi daha iyi. –

2

Christopher ne soran, Görünüşe göre, bir miktar dikkate alındıktan sonra ve sparse.model.matrix vb. neden nolu X_test modelinin tam serpiştirilmiş model matrisini oluşturmak istemediğini açıklamıyorsunuz, bu yüzden aşağıdaki iki seçenek dışında bir yol ileri sunmanız zordur.Eğer X_test gözlemler çok sayıda var ve dolayısıyla hesaplama nedenlerle predict() kullanılmak üzere tam seyrek matris üretmek istemiyorsanız

, örneklerin ve form iki veya daha fazla parçalar halinde X_test bölmek daha uygun olabilir seyrek model her biri için sırayla matrisler, sonra kullanımdan sonra atıyor.

Bunun başarısız olması durumunda, Matrix paketinden ayrıntılı olarak kod çalışması yapmanız gerekecektir. sparse.model.matrix ile başlayın ve daha sonra Matrix:::model.spmatrix numaralı telefonu arayın ve bu işlevdeki çağrıları Matrix:::fac2Sparse olarak bulun. Muhtemelen bu işlevlerden kodları birlikte kullanmanız gerekecektir, ancak başarmak istediğinizi elde etmek için değiştirilmiş bir fac2Sparse kullanın.

Üzgünüz, bunu yapmak için bir hazır komut dosyası sağlayamıyorum, ancak bu önemli bir kodlama görevidir. Bu rotayı aşarsanız, Matrix paketindeki Seyrek Model Matrisleri vignette'i kontrol edin ve kaynak kodunda daha iyi belgelenip belgelenmediğini görmek için (CRAN'dan) paket kaynaklarını (kaynak kodu) alın. Örneğin, fac2Sparse. Matrix'in (Martin Maechler ve Doug Bates) yazarlarına da tavsiyede bulunabilirsiniz, ancak bu birliklerin her ikisinin de bu terimi özellikle ağır bir öğretim yüküne sahip olduklarına dikkat ediniz.

İyi şanslar!