1. ホーム
  2. r

mutate_atで元の変数を維持したまま新しい変数を作成する

2023-09-06 05:22:19

質問

この簡単な例を考えてみましょう。

library(dplyr)

dataframe <- data_frame(helloo = c(1,2,3,4,5,6),
                        ooooHH = c(1,1,1,2,2,2),
                        ahaaa = c(200,400,120,300,100,100))

# A tibble: 6 x 3
  helloo ooooHH ahaaa
   <dbl>  <dbl> <dbl>
1      1      1   200
2      2      1   400
3      3      1   120
4      4      2   300
5      5      2   100
6      6      2   100

ここで、関数を適用したい ntile を含む全てのカラムに対して oo を含むすべてのカラムに適用されますが、これらの新しいカラムは cat + と対応するカラムを追加してください。

私はこれができることを知っている

dataframe %>% mutate_at(vars(contains('oo')), .funs = funs(ntile(., 2)))
# A tibble: 6 x 3
  helloo ooooHH ahaaa
   <int>  <int> <dbl>
1      1      1   200
2      1      1   400
3      1      1   120
4      2      2   300
5      2      2   100
6      2      2   100

しかし、私が必要とするのはこれです。

# A tibble: 8 x 5
  helloo   ooooHH   ahaaa cat_helloo cat_ooooHH
     <dbl>    <dbl> <dbl>    <int>    <int>
1        1        1   200        1        1
2        2        1   400        1        1
3        3        1   120        1        1
4        4        2   300        2        2
5        5        2   100        2        2
6        5        2   100        2        2
7        6        2   100        2        2
8        6        2   100        2        2

中間データを保存して、元のデータフレームにマージする必要がない解決策はありますか?

どのように解決するのですか?

2020-06 dplyr 1.0.0にアップデートしました。

で始まる dplyr 1.0.0 が追加されました。 across() のような関数の "スコープ付きバリアント" に取って代わります。 mutate_at() . このコードは across() の中にネストされている mutate() .

リストで指定した関数に名前を付けると、その関数名がサフィックスとして追加されます。

dataframe %>%
     mutate( across(contains('oo'), 
                    .fns = list(cat = ~ntile(., 2))) )

# A tibble: 6 x 5
  helloo ooooHH ahaaa helloo_cat ooooHH_cat
   <dbl>  <dbl> <dbl>      <int>      <int>
1      1      1   200          1          1
2      2      1   400          1          1
3      3      1   120          1          1
4      4      2   300          2          2
5      5      2   100          2          2
6      6      2   100          2          2

新しいカラム名の変更は、1.0.0 では少し簡単です。 .names 引数で across() . 以下は、関数名をサフィックスではなくプレフィックスとして追加する例です。 これは 接着剤 の構文を使っています。

dataframe %>%
     mutate( across(contains('oo'), 
                    .fns = list(cat = ~ntile(., 2)),
                    .names = "{fn}_{col}" ) )

# A tibble: 6 x 5
  helloo ooooHH ahaaa cat_helloo cat_ooooHH
   <dbl>  <dbl> <dbl>      <int>      <int>
1      1      1   200          1          1
2      2      1   400          1          1
3      3      1   120          1          1
4      4      2   300          2          2
5      5      2   100          2          2
6      6      2   100          2          2

mutate_at()を使ったオリジナルの回答

dplyrの変更を反映するために編集されました。 dplyr 0.8.0時点のものです。 funs() は非推奨となり list()~ が使われるべきです。

に渡すリストに関数の名前を与えることができます。 .funs に渡すと、その名前を接尾辞として付けた新しい変数が作られます。

dataframe %>% mutate_at(vars(contains('oo')), .funs = list(cat = ~ntile(., 2)))

# A tibble: 6 x 5
  helloo ooooHH ahaaa helloo_cat ooooHH_cat
   <dbl>  <dbl> <dbl>      <int>      <int>
1      1      1   200          1          1
2      2      1   400          1          1
3      3      1   120          1          1
4      4      2   300          2          2
5      5      2   100          2          2
6      6      2   100          2          2

もし、プレフィックスとして使いたい場合は rename_at を使って名前を変更します。

dataframe %>% 
     mutate_at(vars(contains('oo')), .funs = list(cat = ~ntile(., 2))) %>%
     rename_at( vars( contains( "_cat") ), list( ~paste("cat", gsub("_cat", "", .), sep = "_") ) )

# A tibble: 6 x 5
  helloo ooooHH ahaaa cat_helloo cat_ooooHH
   <dbl>  <dbl> <dbl>      <int>      <int>
1      1      1   200          1          1
2      2      1   400          1          1
3      3      1   120          1          1
4      4      2   300          2          2
5      5      2   100          2          2
6      6      2   100          2          2

以前のコードで funs() の以前のバージョンから dplyr :

dataframe %>% 
     mutate_at(vars(contains('oo')), .funs = funs(cat = ntile(., 2))) %>%
     rename_at( vars( contains( "_cat") ), funs( paste("cat", gsub("_cat", "", .), sep = "_") ) )