データ フレームに複数の新しい列を作成するために使用したいと思いますdplyr::mutate()
。列名とその内容は動的に生成される必要があります。
iris からのデータの例:
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()
動的な名前を変数名として使用するにはどうすればよいですか?
ベストアンサー1
変数名を文字値として動的に構築するため、列名に文字値を許可する標準の data.frame インデックスを使用して割り当てを行う方が合理的です。例:
multipetal <- function(df, n) {
varname <- paste("petal", n , sep=".")
df[[varname]] <- with(df, Petal.Width * n)
df
}
このmutate
関数を使用すると、名前付きパラメータを介して新しい列に名前を付けるのが非常に簡単になります。ただし、コマンドを入力するときに名前を知っていることが前提となります。列名を動的に指定する場合は、名前付き引数も作成する必要があります。
dplyr バージョン >= 1.0
glue
最新の dplyr バージョンでは、 を使用するときにパラメータに名前を付けるときに、パッケージの構文を使用できます:=
。したがって、ここでは{}
名前の は内部の式を評価することによって値を取得します。
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
を慎重に使用する必要があります。quote
setName
# --- 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)
}