dplyr的filter_中的非标准评估(NSE)和从MySQL中提取数据
我想从一个dynamicfilter的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
这段代码工作正常,但现在我想循环它在我的表的所有列,所以我想写的filter为:
#Dynamic filter i <- 2 #With a loop on this i for instance which_column <- paste0("column",i) filter_criteria <- ~ which_column %in% some_vector
然后用更新的filter重新应用第一个代码。
不幸的是,这种方法没有给出预期的结果。 事实上,它不会给出任何错误,但甚至不会将任何结果拉入R.特别是,我查看了两段代码生成的SQL查询,有一个重要的区别。
第一个工作代码生成一个表单查询:
SELECT ... FROM ... WHERE `column1` IN ....
(`login列名称),第二个生成一个查询的forms:
SELECT ... FROM ... WHERE 'column1' IN ....
('login列名称)
有没有人有任何build议如何制定过滤条件,使其工作?
这不是真的与SQL有关。 R中的这个例子也不起作用:
df <- data.frame( v1 = sample(5, 10, replace = TRUE), v2 = sample(5,10, replace = TRUE) ) df %>% filter_(~ "v1" == 1)
它不起作用,因为你需要传递filter_
expression式filter_
~ v1 == 1
– 而不是expression式~ "v1" == 1
。
dplyr版本> = 0.6
要解决这个问题,只需使用引号操作符和引号操作符!!
library(dplyr) which_column = quot(v1) df %>% filter(!!which_column == 1)
dplyr版本<0.6
为了解决这个问题,使用lazyeval包中的函数interp。
library(lazyeval) filter_criteria <- interp(~ which_column == 1, which_column = as.name("v1")) df %>% filter_(filter_criteria)
下面是一个稍微不详细的解决scheme,其中一个使用了提取函数的典型行为: '['
在按字符值select列而不是将其转换为语言元素:
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
另一种解决方法是,使用dplyr版本0.5.0(可能早于实现),可以传递一个组合的string作为.dots参数,我发现它比lazyeval :: interp解决scheme更具可读性:
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是一个stringvariables。)