1. ホーム
  2. r

[解決済み] `dplyr`で新しいカラム/変数に動的な名前を使用する

2022-04-16 16:36:28

質問

を使いたいのですが dplyr::mutate() を使用して、データフレームに複数の新しい列を作成します。列名とその内容は動的に生成される必要があります。

虹彩のデータ例。

library(dplyr)
iris <- as_tibble(iris)

新しいカラムを変異させるための関数を Petal.Width 変数を使用します。

multipetal <- function(df, n) {
    varname <- paste("petal", n , sep=".")
    df <- mutate(df, varname = Petal.Width * n)  ## problem arises here
    df
}

ここで、カラムを構築するためのループを作成します。

for(i in 2:5) {
    iris <- multipetal(df=iris, n=i)
}

しかし、mutate は varname をリテラルな変数名とみなしているので、ループは4つの新しい変数(petal.2 - petal.5 と呼ばれる)ではなく、1つの新しい変数(varname と呼ばれる)を作成するだけです。

どうすれば mutate() を使うと、ダイナミック名を変数名として使用できますか?

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

変数名を文字値として動的に構築しているので、列名に文字値を使用できる標準的な data.frame インデックスを使用して割り当てを行う方がより理にかなっています。例えば、以下のようになります。

multipetal <- function(df, n) {
    varname <- paste("petal", n , sep=".")
    df[[varname]] <- with(df, Petal.Width * n)
    df
}

mutate 関数を使用すると、名前付きパラメータを使用して新しいカラムに名前を付けるのが非常に簡単になります。しかし、これはコマンドを入力するときに名前を知っていることが前提です。もしカラム名を動的に指定したいのであれば、名前付き引数も作成する必要があります。


dplyr バージョン >= 1.0

dplyrの最新バージョンでは、この構文で glue パッケージを使用している場合、パラメータに名前を付ける際に := . そのため、ここでは {} の中にある式を評価することによって値を取得します。

multipetal <- function(df, n) {
  mutate(df, "petal.{n}" := Petal.Width * n)
}

関数にカラム名を渡す場合は {{}} という文字列を、カラム名と同様に

meanofcol <- function(df, col) {
  mutate(df, "Mean of {{col}}" := mean({{col}}))
}
meanofcol(iris, Petal.Width)



dplyr バージョン >= 0.7

dplyr バージョン0.7からは := を使用して、パラメータ名を動的に割り当てることができます。というように関数を書くことができます。

# --- dplyr version 0.7+---
multipetal <- function(df, n) {
    varname <- paste("petal", n , sep=".")
    mutate(df, !!varname := Petal.Width * n)
}

詳細については、利用可能なドキュメントフォームを参照してください。 vignette("programming", "dplyr") .


dplyr (>=0.3 & <0.7)

の少し前のバージョンです。 dplyr (>=0.3 <0.7) では、多くの関数で "標準評価" の代替を使用することを推奨していました。詳しくは、非標準評価ビネットをご覧ください ( vignette("nse") ).

つまり、ここでは、答えは mutate_() よりも mutate() とやってください。

# --- dplyr version 0.3-0.5---
multipetal <- function(df, n) {
    varname <- paste("petal", n , sep=".")
    varval <- lazyeval::interp(~Petal.Width * n, n=n)
    mutate_(df, .dots= setNames(list(varval), varname))
}


dplyr < 0.3

の古いバージョンでも可能であることに注意してください。 dplyr は、その質問が最初に出されたときに存在したものです。を慎重に使用する必要があります。 quotesetName :

# --- dplyr versions < 0.3 ---
multipetal <- function(df, n) {
    varname <- paste("petal", n , sep=".")
    pp <- c(quote(df), setNames(list(quote(Petal.Width * n)), varname))
    do.call("mutate", pp)
}