2

次のようなデータフレームがあります。

d<-data.frame(id=(1:9), 
                  grp_id=(c(rep(1,3), rep(2,3), rep(3,3))), 
                  a=rep(NA, 9), 
                  b=c("No", rep(NA, 3), "Yes", rep(NA, 4)), 
                  c=c(rep(NA,2), "No", rep(NA,6)), 
                  d=c(rep(NA,3), "Yes", rep(NA,2), "No", rep(NA,2)), 
                  e=c(rep(NA, 7), "No", NA), 
                  f=c(NA, "No", rep(NA,3), "No", rep(NA,2), "No"))
>d
  id grp_id  a    b    c    d    e    f
1  1      1 NA   No <NA> <NA> <NA> <NA>
2  2      1 NA <NA> <NA> <NA> <NA>   No
3  3      1 NA <NA>   No <NA> <NA> <NA>
4  4      2 NA <NA> <NA>  Yes <NA> <NA>
5  5      2 NA  Yes <NA> <NA> <NA> <NA>
6  6      2 NA <NA> <NA> <NA> <NA>   No
7  7      3 NA <NA> <NA>   No <NA> <NA>
8  8      3 NA <NA> <NA> <NA>   No <NA>
9  9      3 NA <NA> <NA> <NA> <NA>   No

各グループ (grp_id) 内には、各列 a:f に関連付けられた「はい」または「いいえ」の値が 1 つだけあります。

次のようなデータ フレームを取得するために、各 grp_id に対して単一の行を作成したいと思います。

grp_id  a    b    c    d    e    f
     1 NA   No   No <NA> <NA>   No
     2 NA  Yes <NA>  Yes <NA>   No
     3 NA <NA> <NA>   No   No   No

tidyr パッケージがおそらく最良のツールであり、最初のステップはおそらく

d %>% 
   group_by(grp_id) %>%
     summarise()

要約内のコマンド、または実際の解決策について助けていただければ幸いです。ありがとう。

4

3 に答える 3

1

summarise_at最初の非 NA 要素を使用してサブセット化できます

library(dplyr)
d %>%
   group_by(grp_id) %>%
   summarise_at(2:7, funs(.[!is.na(.)][1]))
# A tibble: 3 x 7
#   grp_id     a      b      c      d      e      f
#    <dbl> <lgl> <fctr> <fctr> <fctr> <fctr> <fctr>
#1      1    NA     No     No   <NA>   <NA>     No
#2      2    NA    Yes   <NA>    Yes   <NA>     No
#3      3    NA   <NA>   <NA>     No     No     No

サンプル データセットでは、列 'a' から 'f' はすべてfactors、一部は 'No' レベルのみです。すべての列が同じ を持つように標準化する必要がある場合は、ieのように指定されたwithlevelsを呼び出す必要がある場合があります。factorlevelsc('Yes', 'No')summarise_atsummarise_at(2:7, funs(factor(.[!is.na(.)][1], levels = c('Yes', 'No'))))

于 2017-11-19T18:45:08.437 に答える
1

いくつかの良い回答を受け取りましたが、どちらも実際にtidyrパッケージを使用していません。( summarize()andsummarize_at()ファミリの関数は からのものdplyrです。)

実際、tidyrあなたの問題に対する唯一の解決策は非常に実行可能です。

d %>%
    gather(col, value, -id, -grp_id, factor_key=TRUE) %>%
    na.omit() %>%
    select(-id) %>%
    spread(col, value, fill=NA, drop=FALSE)

a唯一の難しい部分は、出力で列を確実に取得することです。サンプル データの場合、完全にNA. トリックは へのfactor_key=TRUE引数と へgather()drop=FALSE引数spread()です。これらの 2 つの引数が設定されていない場合、出力にはa列がなく、少なくとも 1 つの非NAエントリを含む列のみが含まれます。

これがどのように機能するかの説明は次のとおりです。

gather(col, value, -id, -grp_id, factor_key=TRUE) %>%

これにより、データが整理され、列が効果的に置き換えられaf新しい列colvalueが作成され、長い形式の「整理された」データ フレームが形成されます。列のエントリcolは文字a-fです。また、 を使用したためfactor_key=TRUE、この列は単なる文字ベクトルではなく、レベルをもつ因子です。

na.omit() %>%

NAこれにより、長いデータからすべての値が削除されます。

select(-id) %>%

これにより、列が削除されidます。

spread(col, value, fill=NA, drop=FALSE)

colこれにより、列の値を使用して新しい列名を定義し、列の値を使用しvalueて新しい列のエントリを入力して、データを再度広げます。データが欠落している場合は、代わりにfill(ここでNAは ) の値が使用されます。また、drop=FALSEwhencolが因子である場合、その水準がデータに表示されるかどうかに関係なく、因子の水準ごとに 1 つの列が存在することを意味します。colこれは、要因となる設定とともにa、出力列として得られるものです。

個人的には、このアプローチは、サブセット化などを必要とするアプローチよりも読みやすいと思いますlapply。さらに、データが実際にワンホットでない場合、このアプローチは失敗しますが、他のアプローチは「機能」して予期しない出力が得られる可能性があります。このアプローチの欠点は、出力列が因子afはなく文字ベクトルであることです。ファクター出力が必要な場合は、できるはずです(テストされていません)

mutate(value = factor(value, levels=c('Yes', 'No', NA))) %>%

gather()と関数の間の任意の場所で、spread()因子出力を確保します。

于 2017-11-20T23:33:59.977 に答える