web-dev-qa-db-ja.com

dplyrの関数で変数名を使用する

dplyrの関数で文字列として変数名を使用したい。以下の例を参照してください。

df <- data.frame( 
      color = c("blue", "black", "blue", "blue", "black"), 
      value = 1:5)
filter(df, color == "blue")

完全に機能しますが、次のような文字列でcolorを参照したいと思います。

var <- "color"
filter(df, this_probably_should_be_a_function(var) == "blue").

どうにかしてこれを実現できれば幸いであり、読みやすいdplyr構文を使用できることを嬉しく思います。

37
kuba

dplyrバージョン[0.3-0.7)(?-2017年6月)

(最新のdplyrバージョンについては、この質問に対する他の回答をご覧ください)

dplyr 0.3現在、非標準評価(NSE、 リリース投稿 および ビネット を参照)を使用するすべてのdplyr関数には、標準評価(SE)ツインがありますアンダースコアで終わる。これらは変数を渡すために使用できます。 filterの場合、filter_になります。 filter_を使用すると、論理条件を文字列として渡すことができます。

filter_(df, "color=='blue'")

#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4

論理条件を使用して文字列を構築することはもちろん簡単です

l <- paste(var, "==",  "'blue'")
filter_(df, l)
27
Mark Heckmann

新しいバージョンでは、変数を引用符で囲んで作成し、引用符を外す(UQまたは!!)評価用

var <- quo(color)
filter(df, UQ(var) == "blue")
#   color value
#1  blue     1
#2  blue     3
#3  blue     4

演算子の優先順位により、()折り返す!!

filter(df, (!!var) == "blue")
#   color value
#1  blue     1
#2  blue     3
#3  blue     4

新しいバージョンでは、||は優先順位が高いため、

filter(df, !! var == "blue")

動作するはずです(@Moody_Mudskipperがコメントしたとおり)

古いオプション

以下も使用できます。

 filter(df, get(var, envir=as.environment(df))=="blue")
 #color value
 #1  blue     1
 #2  blue     3
 #3  blue     4

編集:ソリューションの順序を並べ替えました

26
akrun

Dplyr 0.7の時点で、いくつかの点が再び変更されました。

library(dplyr)
df <- data.frame( 
  color = c("blue", "black", "blue", "blue", "black"), 
  value = 1:5)
filter(df, color == "blue")

# it was already possible to use a variable for the value
val <- 'blue'
filter(df, color == val)

# As of dplyr 0.7, new functions were introduced to simplify the situation
col_name <- quo(color) # captures the current environment
df %>% filter((!!col_name) == val)

# Remember to use enquo within a function
filter_col <- function(df, col_name, val){
  col_name <- enquo(col_name) # captures the environment in which the function was called
  df %>% filter((!!col_name) == val)
}
filter_col(df, color, 'blue')

より一般的なケースは dplyrプログラミングビネット で説明されています。

16
takje

よく尋ねられますが、まだ簡単なサポートはありません。ただし、 この投稿 に関しては:

eval(substitute(filter(df, var == "blue"), 
                list(var = as.name(var))))
#   color value
# 1  blue     1
# 2  blue     3
# 3  blue     4
7
lukeA

rlangパッケージのsym()関数を使用してそれを行う1つの方法を次に示します。

library(dplyr)

df <- data.frame( 
  main_color = c("blue", "black", "blue", "blue", "black"), 
  secondary_color = c("red", "green", "black", "black", "red"),
  value = 1:5, 
  stringsAsFactors=FALSE
)

filter_with_quoted_text <- function(column_string, value) {
    col_name <- rlang::sym(column_string)
    df1 <- df %>% 
      filter(UQ(col_name) == UQ(value))
    df1
}

filter_with_quoted_text("main_color", "blue")
filter_with_quoted_text("secondary_color", "red")
4
Tom Roth

rlang version> = 0.4.0の新機能

.dataは親データフレームを参照する方法として認識されるようになったため、文字列による参照は次のように機能します。

var <- "color"
filter(df, .data[[var]] == "blue")

変数が既にシンボルである場合、{{}}は適切に逆参照します

例1:

var <- quo(color)
filter(df, {{var}} == "blue")

またはより現実的に

f <- function(v) {
    filter(df, {{v}} == "blue")
}
f(color)
1
Ben Bolker