web-dev-qa-db-ja.com

MySQLからのdplyrのfilter_およびプルデータの非標準評価(NSE)

動的フィルターを使用してSQLサーバーからデータをプルしたいのですが。私は次のように素晴らしいRパッケージdplyrを使用しています:

#Create the filter
filter_criteria = ~ column1 %in% some_vector
#Connect to the database
connection <- src_mysql(dbname <- "mydbname", 
             user <- "myusername", 
             password <- "mypwd", 
             Host <- "myhost") 
#Get data
data <- connection %>%
 tbl("mytable") %>% #Specify which table
 filter_(.dots = filter_criteria) %>% #non standard evaluation filter
 collect() #Pull data

このコードは正常に機能しますが、テーブルのすべての列でなんとかしてループさせたいので、フィルターを次のように記述します。

#Dynamic filter
i <- 2 #With a loop on this i for instance
which_column <- paste0("column",i)
filter_criteria <- ~ which_column %in% some_vector

そして、更新されたフィルターを使用して最初のコードを再適用します。

残念ながら、このアプローチでは期待した結果が得られません。実際、エラーは発生しませんが、結果がRに取り込まれることはありません。特に、2つのコードによって生成されたSQLクエリを少し調べたところ、重要な違いが1つあります。

最初の機能するコードは、次の形式のクエリを生成します。

SELECT ... FROM ... WHERE 
`column1` IN ....

( `は列名にサインインします)、2番目は次の形式のクエリを生成します:

SELECT ... FROM ... WHERE 
'column1' IN ....

( '列名にサインイン)

フィルタリング条件を定式化して機能させる方法について何か提案はありますか?

31
Lorenzo Rossi

SQLとは実際には関係ありません。このRの例も機能しません。

df <- data.frame(
     v1 = sample(5, 10, replace = TRUE),
     v2 = sample(5,10, replace = TRUE)
)
df %>% filter_(~ "v1" == 1)

filter_に式~ v1 == 1ではなく式~ "v1" == 1を渡す必要があるため、機能しません。

この問題を解決するには、引用演算子quoと引用解除演算子!!を使用するだけです。

library(dplyr)
which_column = quot(v1)
df %>% filter(!!which_column == 1)
43
Matthew

Dplyrバージョン0.5.0(おそらくそれより前に実装された)の代替ソリューションでは、合成文字列を.dots引数として渡すことができます。これは、lazyeval :: interpソリューションよりも読みやすくなっています。

df <- data.frame(
     v1 = sample(5, 10, replace = TRUE),
     v2 = sample(5,10, replace = TRUE)
)

which_col <- "v1"
which_val <- 1
df %>% filter_(.dots= paste0(which_col, "== ", which_val))

  v1 v2
1  1  1
2  1  2
3  1  4

[〜#〜] update [〜#〜]for dplyr 0.6以降:

packageVersion("dplyr")
# [1] ‘0.5.0.9004’

df %>% filter(UQ(rlang::sym(which_col))==which_val)
#OR
df %>% filter((!!rlang::sym(which_col))==which_val)

(dplyr 0.6の@Matthewの応答と同様ですが、which_colは文字列変数であると想定しています。)

2回目の更新:Edwin Thoenが整頓された評価用のニースのチートシートを作成しました: https://edwinth.github.io/blog/dplyr-recipes /

8
LmW.

これは少し冗長なソリューションであり、extract関数の標準的な動作を使用するソリューションであり、言語要素に変換するのではなく、文字値で列を選択するときに'['を使用します。

df %>% filter(., '['(., which_column)==1 )

set.seed(123)
df <- data.frame(
      v1 = sample(5, 10, replace = TRUE),
      v2 = sample(5,10, replace = TRUE)
 )
which_column <- "v1"
df %>% filter(., '['(., which_column)==1)
#  v1 v2
#1  1  5
5
42-