簡體   English   中英

dplyr的filter_中的非標准評估(NSE)和從MySQL中提取數據

[英]Non-standard evaluation (NSE) in dplyr's filter_ & pulling data from MySQL

我想從帶有動態過濾器的sql server中提取一些數據。 我正在以下列方式使用偉大的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.特別是,我看了兩個代碼生成的SQL查詢,並且有一個重要的區別。

第一個工作代碼生成表單的查詢:

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

(`登錄列名),第二個生成表單的查詢:

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和dequoting操作!!

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

更新 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)

(類似於@Matthew對dplyr 0.6的響應,但我假設which_col是一個字符串變量。)

第二次更新 :Edwin Thoen為整潔的評估創建了一個很好的備忘單: https ://edwinth.github.io/blog/dplyr-recipes/

這是一個稍微簡潔的解決方案,它使用提取函數的典型行為, '['選擇逐字符值而不是將其轉換為語言元素:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM