動的フィルターを使用して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 ....
( '列名にサインイン)
フィルタリング条件を定式化して機能させる方法について何か提案はありますか?
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)
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 /
これは少し冗長なソリューションであり、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