1

I have a data frame like

> x = data.frame(A=c(1,2,3),B=c(2,3,4))
> x
  A B
1 1 2
2 2 3
3 3 4

and subsetting conditions in a data frame like

> cond = data.frame(condition=c('A>1','B>2 & B<4'))
> cond
  condition
1       A>1
2 B>2 & B<4

which I then apply dynamically

> eval(parse(text=paste0("subset(x,",cond[1,'condition'],")")))
  A B
2 2 3
3 3 4
> eval(parse(text=paste0("subset(x,",cond[2,'condition'],")")))
  A B
2 2 3

Now, instead of subsetting, I would like to add the subsetting conditions as variables into the data. The end result would look like

  A B condition1 condition2
1 1 2          0          0  
2 2 3          1          1
3 3 4          1          0

How could I derive the above table using the dynamic conditions?

Heikki
  • 2,214
  • 19
  • 34
  • 2
    `x <- data.frame(A=c(1,2,3), B=c(2,3,4)); condition <- c('A>1','B>2 & B<4'); with(x, sapply(condition, function(cond) eval(parse(text=cond))))` – jogo Apr 03 '19 at 08:06

2 Answers2

2

Before using eval parse, I hope you have gone through some readings like

What specifically are the dangers of eval(parse(…))?

and many others which are available.

However, to answer your question, we can continue your flow and use eval parse in sapply

+(sapply(seq_len(nrow(cond)), function(i) 
            eval(parse(text=paste0("with(x,",cond[i,'condition'],")")))))

#     [,1] [,2]
#[1,]    0    0
#[2,]    1    1
#[3,]    1    0

To add it to the dataframe,

x[paste0("condition", 1:nrow(cond))] <- 
         +(sapply(seq_len(nrow(cond)), function(i) 
         eval(parse(text=paste0("with(x,",cond[i,'condition'],")")))))

x
#  A B condition1 condition2
#1 1 2          0          0
#2 2 3          1          1
#3 3 4          1          0

Simplifying it a bit (using @jogo's comment)

+(sapply(cond$condition, function(i) with(x, eval(parse(text=as.character(i))))))

#     [,1] [,2]
#[1,]    0    0
#[2,]    1    1
#[3,]    1    0
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Yes, read those warnings on using `eval`and `parse`. I am reusing the conditions in several places, therefore they are in a table. – Heikki Apr 03 '19 at 08:09
  • 2
    So it was actually the `with` syntax which I was looking for: `subset(x, A>1)` vs. `with(x, A>1)`. – Heikki Apr 03 '19 at 08:23
0

Here is an option using tidyverse

library(tidyverse)
x %>%   
  mutate(!!! rlang::parse_exprs(str_c(cond$condition, collapse=";"))) %>% 
  rename_at(3:4, ~ paste0("condition", 1:2))
#  A B condition1 condition2
#1 1 2      FALSE      FALSE
#2 2 3       TRUE       TRUE
#3 3 4       TRUE      FALSE

If needed, the logical columns can be easily converted to binary with as.integer

akrun
  • 874,273
  • 37
  • 540
  • 662