2016-10-03 9 views
4

mtcarsデータセットのgpm(1マイル当たりのガロン= 1/mpg)のモデルをwtにフィッティングするのと同じことをしたいと思います。それは簡単だと思われます:broomとdplyrを使用してグループ化されたデータをグループ化されたモデルに適用するにはどうすればよいですか?

data(mtcars) 
library(dplyr) 
library(tidyr) 
library(broom) 
library(ggplot2) 
library(scales) 

mtcars2 <- 
    mtcars %>% 
    mutate(gpm = 1/mpg) %>% 
    group_by(cyl, am) 

lm1 <- 
    mtcars2 %>% 
    do(fit = lm(gpm ~ wt, data = .)) 

これは私に6行のローのデータフレームを期待どおりに取得します。

このグラフは、6つのグループが存在することを確認:

lm1 %>% augment(fit) 

私は32行、行ごとに一を与える:

p1 <- 
    qplot(wt, gpm, data = mtcars2) + 
    facet_grid(cyl ~ am) + 
    stat_smooth(method='lm',se=FALSE, fullrange = TRUE) + 
    scale_x_continuous(limits = c(0,NA)) 

Iはフィット出力を得るために)(増補を使用することができ期待どおりのmtcars2。今

挑戦:私は、これは、同じサイズのデータ​​フレームを生成することを期待

newdata <- 
    mtcars2 %>% 
    mutate(
     wt = wt + cyl/4) 

:私はCYL/4で重量をインクリメントしましNEWDATAを、使用してフィット出力を取得したいのですがlm1%>%augment(fit):newdataの各行に対して1行。cylとamのグループ化変数によってモデルと新データが一致します。

残念なことに、

pred1 <- 
    lm1 %>% 
    augment(
     fit, 
     newdata = newdata) 

は明らかNEWDATAの各行にそれぞれのモデルをフィッティング、私の192行(= 6×32)を有するデータフレームを与えます。

他の場所から読んだところでは、group_byとrowwiseデータフレームは互換性がないため、lm1はグループ化されず、augmentはモデルとnewdataを関連付けることができません。これを可能にする別のデザインパターンはありますか?上記の試みと同じくらいシンプルで透明であればいいですが、もっと重要です。

> sessionInfo() 
R version 3.3.1 (2016-06-21) 
Platform: x86_64-w64-mingw32/x64 (64-bit) 
Running under: Windows 7 x64 (build 7601) Service Pack 1 

locale: 
[1] LC_COLLATE=English_United States.1252 
[2] LC_CTYPE=English_United States.1252 
[3] LC_MONETARY=English_United States.1252 
[4] LC_NUMERIC=C       
[5] LC_TIME=English_United States.1252  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] scales_0.4.0 ggplot2_2.1.0 broom_0.4.1 tidyr_0.6.0 dplyr_0.5.0 

loaded via a namespace (and not attached): 
[1] Rcpp_0.12.7  magrittr_1.5  mnormt_1.5-4  munsell_0.4.3 
[5] colorspace_1.2-6 lattice_0.20-34 R6_2.1.3   stringr_1.1.0 
[9] plyr_1.8.4  tools_3.3.1  parallel_3.3.1 grid_3.3.1  
[13] nlme_3.1-128  gtable_0.2.0  psych_1.6.9  DBI_0.5-1  
[17] lazyeval_0.2.0 assertthat_0.1 tibble_1.2  reshape2_1.4.1 
[21] labeling_0.3  stringi_1.1.1 compiler_3.3.1 foreign_0.8-67 

EDIT:

@aosmith:

はここに私のSessionInfo()だ私はあなたの2番目のオプションを模索してきた、と私はそれが好きです。私が実際のデータで試してみると、mutateコマンドに問題があります。「エラー:augmentはクラスリストのデータを処理する方法を知らない」という結果を返します。

私の実際のコードはもっと似ている:

newdata %>% 
dplyr::select(cyl, am, wt) %>% # wt holds new predictor values 
group_by(cyl, am) %>% 
nest() %>% 
inner_join(regressions, .) %>% 
## looks like yours at this point 
mutate(pred = list(augment(fit, newdata = data))) %>% # Error here 
unnest(pred) 

私はそれがあなたのように見えると言う場合は、私は次の列(一貫性のために、ここで名前を変更)を持っている意味:ID(CHR)、ATTR1(DBL)、 cyl(dbl)、am(chr)、fit(list)、およびdata(list)です。 cyl、am(dbl)、フィット、およびデータがあります。私は私のAMをDBLに変更したが、それは役に立たなかった。

私は、このサンプル(12個の測定値を持つ各サンプル)で3(ID ... mtcarsのrownamesに似ています)x 2(cyl)x 2 mtcarsの例では、セルあたり3(cyl)x 2(am)のセルタイプの乱数があります。私の分析では、ID値を確認する必要がありますが、newdataはすべてのユニットに均等に適用されます。それが助けになるならば、それをテスト中の各車に適用される逆風の速度と考えてください。これは、クラスリストのデータを扱うことができないという補足の苦情の原因を示唆していますか?

EDIT:IDをnewdataとマージすると(full = TRUEを使用)、最後の問題が解決されました。私は現在、あなたの最初に提案されたソリューションを使用しています。

答えて

4

この種の状況では、私はmap2のパッケージのpurrrを使用しました。 map2は、2つのリストの要素を同時にループします。リストは同じ長さで、同じ順序でなければなりません。

リストの要素は、適用する関数の引数として使用されます(augment、あなたの場合)。ここでは、2つのリストがモデルのリストとデータセットのリスト(それぞれcyl/amの組み合わせのリスト)になります。

map2_dfを使用すると、リストの代わりにdata.frameとして結果が返されます。

library(purrr) 

私はsplitを使用して予測するdata.framesのリストを作りました。分割する要素の順序がリストの順序を決定したので、それはlm1と同じ順序であることを確認しました。そんなに順序を心配避けるため

test_split = split(newdata, list(newdata$am, newdata$cyl) 

map2_df(lm1$fit, test_split, ~augment(.x, newdata = .y)) 

、あなたは、グループによって予測データをnestlm1にこれに参加し、ネスト解除のためのリストとしてaugmentの結果を返すことができます。

newdata %>% 
    group_by(cyl, am) %>% 
    nest() %>% 
    inner_join(lm1, .) %>% 
    mutate(pred = list(augment(fit, newdata = data))) %>% 
    unnest(pred) 
関連する問題