Is there a way to do filter with a string as parameter without using eval(parse())?
library("dplyr")
subset <- "carb == 4"
subset_df <- mtcars %>% filter(eval(parse(text = subset)))
Is there a way to do filter with a string as parameter without using eval(parse())?
library("dplyr")
subset <- "carb == 4"
subset_df <- mtcars %>% filter(eval(parse(text = subset)))
1) rlang If what you are asking is whether there are counterparts to eval/parse in the tidyverse then, yes, there are. You will also need rlang which is already used by dplyr but dplyr does not export the functions needed so use a library statement to load it.
library(dplyr)
library(rlang)
subset <- "carb == 4"
mtcars %>% filter(eval_tidy(parse_expr(subset)))
giving:
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
1a) This also works:
mtcars %>% filter(!!parse_quo(subset, .GlobalEnv))
2) sqldf If you are looking for a way to do this without using eval/parse or any direct alternative to it and it is not required to use the tidyverse then sqldf can do that provided subset
contains valid SQL which in the case of the question it does.
library(sqldf)
subset <- "carb == 4"
fn$sqldf("select * from mtcars where $subset")
giving:
mpg cyl disp hp drat wt qsec vs am gear carb
1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
3 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
4 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
5 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
6 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
7 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
8 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
9 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
10 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
2a) This can also be written in terms of pipes like this:
mtcars %>% { fn$sqldf("select * from '.' where $subset") }
It is deprecated, but you could use filter_
mtcars %>%
filter_("carb == 4")
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
If we can use a function, then we can pass it as unquoted and evaluate it in {{}}
i.e. we don't need another package nor do any eval/parse
library(dplyr)
f1 <- function(data, expr) {
data %>%
filter({{expr}})
}
-testing
> f1(mtcars, carb == 4)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
Also, if we want to pass from an object, instead of creating a string, quote
it
expr1 <- quote(carb == 4)
f1(mtcars, !!expr1)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4