Home > Back-end >  How can i pass to which function string with logical expresion in R?
How can i pass to which function string with logical expresion in R?

Time:11-05

I want to make data subset with logical expression i have stored in string, like this:

logical_var = paste0("input_dataset$","heigth >= 1.60")

but i cant use it as

subset_data <- input_dataset[ which(logical_var), ]

or

subset_data <- input_dataset[ which(as.logical(logical_var)), ]

because it makes obvious syntax error. From documentation i understand, that wchich() takes only logical expressions.

The effect I want to get would be as in such expression:

subset_data <- input_dataset[ which(input_dataset$heigth >= 1.60), ]

but I don't know the selection condition in advance, I read it from a specific variable.

What should i do with it?

CodePudding user response:

eval(str2lang()) is one way to do it:

str2lang is a shortcut for parse(text = ..., source = FALSE) which is another option.

logical_var = paste0("iris$","Sepal.Length >= 6.5")

iris[eval(str2lang(logical_var)),]

#>     Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
#> 51           7.0         3.2          4.7         1.4 versicolor
#> 53           6.9         3.1          4.9         1.5 versicolor
#> 55           6.5         2.8          4.6         1.5 versicolor
#> 59           6.6         2.9          4.6         1.3 versicolor
#> 66           6.7         3.1          4.4         1.4 versicolor
#> 76           6.6         3.0          4.4         1.4 versicolor
#> 77           6.8         2.8          4.8         1.4 versicolor
#> 78           6.7         3.0          5.0         1.7 versicolor
#> 87           6.7         3.1          4.7         1.5 versicolor
#> 103          7.1         3.0          5.9         2.1  virginica
#> 105          6.5         3.0          5.8         2.2  virginica
#> 106          7.6         3.0          6.6         2.1  virginica
#> 108          7.3         2.9          6.3         1.8  virginica
#> 109          6.7         2.5          5.8         1.8  virginica
#> 110          7.2         3.6          6.1         2.5  virginica
#> 111          6.5         3.2          5.1         2.0  virginica
#> 113          6.8         3.0          5.5         2.1  virginica
#> 117          6.5         3.0          5.5         1.8  virginica
#> 118          7.7         3.8          6.7         2.2  virginica
#> 119          7.7         2.6          6.9         2.3  virginica
#> 121          6.9         3.2          5.7         2.3  virginica
#> 123          7.7         2.8          6.7         2.0  virginica
#> 125          6.7         3.3          5.7         2.1  virginica
#> 126          7.2         3.2          6.0         1.8  virginica
#> 130          7.2         3.0          5.8         1.6  virginica
#> 131          7.4         2.8          6.1         1.9  virginica
#> 132          7.9         3.8          6.4         2.0  virginica
#> 136          7.7         3.0          6.1         2.3  virginica
#> 140          6.9         3.1          5.4         2.1  virginica
#> 141          6.7         3.1          5.6         2.4  virginica
#> 142          6.9         3.1          5.1         2.3  virginica
#> 144          6.8         3.2          5.9         2.3  virginica
#> 145          6.7         3.3          5.7         2.5  virginica
#> 146          6.7         3.0          5.2         2.3  virginica
#> 148          6.5         3.0          5.2         2.0  virginica

Created on 2022-11-04 with reprex v2.0.2

You can also wrap it in which() for the handling of NA's.

iris[which(eval(str2lang(logical_var))),]

CodePudding user response:

1) do.call/subset/parse Use do.call/subset/parse like this. It does not use eval or any packages.

Subset <- function(data, cond) {
  do.call("subset", list(data, parse(text = cond)))
}

# test
Subset(iris, "Sepal.Length > 5.5 & Species == 'setosa'")

giving:

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
15          5.8         4.0          1.2         0.2  setosa
16          5.7         4.4          1.5         0.4  setosa
19          5.7         3.8          1.7         0.3  setosa
> 

2) sql If we specify the condition using SQL syntax then it can be done like this. We surrounded Sepal.Length with square brackets since otherwise dot is an SQL operator. The output is the same as above.

library(sqldf)
Subset2 <- function(data, cond) {
  fn$sqldf("select * from data where $cond")
}
Subset2(iris, "[Sepal.Length] > 5.5 and Species == 'setosa'")
  • Related