

以下のようなデータフレームdfがあるのですが、

[code]

    id category
    1   3
    2   2
    3   3
    4   1
    5   2
    6   2
    
[/code]

これを

[code]

    id category1 category2 category3
    1   0         0         1
    2   0         1         0
    3   0         0         1
    4   1         0         0
    5   0         1         0
    6   0         1         0
    
[/code]

のような形にしたいと考えています。  
現在はこれを

[code]

    df <- tidyr::spread(df,category,category) #横展開
    df.id <- df[,1] #そのままやるとid列も1になってしまうため分離
    df.other <- df[,-1]
    df.other[!is.na(df.other)] <- 1
    df.other[is.na(df.other)] <- 0
    df <- cbind(df.id,df.other)
    
[/code]

としているのですが、もう少しスマートな方法はないでしょうか？  
どなたかご教授お願い致します。


CC BY-SA 3.0
2016-12-17T06:42:35.193
31198
2017-01-08T07:04:34.983
19942
question
r
整数の入った列を横展開して1,0に変換したい


スマートかどうかは分かりませんが、、以下は `apply` を使う場合です。

[code]

    > df[paste('category', sort(unique(df$category)), sep='')] <- 0
    > data.frame(t(apply(df, 1,
        function(r){
          r[paste('category', r['category'], sep='')] <- 1
          r[-c(2)]
        })))
    
      id category1 category2 category3
    1  1         0         0         1
    2  2         0         1         0
    3  3         0         0         1
    4  4         1         0         0
    5  5         0         1         0
    6  6         0         1         0
    
[/code]

`apply(df, 1, ...)` とすることでデータフレームを行ごとに処理します。また、`r[-c(2)]` でデータフレームの `category`
カラムを削除しています。


CC BY-SA 3.0
2016-12-17T10:45:24.963
31203
2016-12-17T11:09:39.860
2016-12-17T11:09:39.860
31198
answer


その作業はdummy変数の作成などと呼ばれ、`dummies` や `caret` 等のパッケージがそれ用の関数を持っています。私の一押しは
`makedummies` パッケージです。

[code]

    # install.packages("makedummies")
    library(makedummies)
    
    df$category <- as.factor(df$category)  # makedummies()はファクターを1,0に横展開します
    makedummies(df, basal_level = TRUE)    # basal_level = T で第1カテゴリ列も作成されます
    
    #   id category_1 category_2 category_3
    # 1  1          0          0          1
    # 2  2          0          1          0
    # 3  3          0          0          1
    # 4  4          1          0          0
    # 5  5          0          1          0
    # 6  6          0          1          0
    
[/code]


CC BY-SA 3.0
2016-12-18T01:52:26.120
31212
2017-01-08T07:04:34.983
2017-01-08T07:04:34.983
15653
15653
31198
answer


`base`の`model.matrix`が使える:

[code]

    x = data.frame(id = 1:6, category = c(3, 2, 3, 1, 2, 2))
    
[/code]

`category`を`factor`に変えよう:

[code]

    x$category = factor(x$category)
    
    model.matrix(~catgory - 1, data = x)
    
    #   category1 category2 category3
    # 1         0         0         1
    # 2         0         1         0
    # 3         0         0         1
    # 4         1         0         0
    # 5         0         1         0
    # 6         0         1         0
    
[/code]

`-1`は「部分を除け」と示して、すべて`category`のレベルを含みます。


CC BY-SA 3.0
2016-12-18T18:24:48.523
31226
2016-12-19T13:23:16.037
2016-12-19T13:23:16.037
15185
18598
31198
answer


{tidyverse}だとこうでしょうか

[code]

    tidyr::spread(df,category,category) %>%
      dplyr::mutate_each(funs(ifelse(is.na(.), 0, 1)), -id)
    
[/code]


CC BY-SA 3.0
2016-12-19T10:25:56.623
31240
2016-12-19T10:25:56.623
19075
31198
answer


makedummiesパッケージの作者です。  
ダミー変数に変換したい列が複数ある場合にはmakedummiesを試してみて下さい。

つい最近CRANに登録されました。


CC BY-SA 3.0
2017-01-04T08:02:28.103
31608
2017-01-04T08:02:28.103
20086
31198
answer