6

I have a logical operator and a numeric value I want to pass as a single element to a statement in a function (I hear hundreds of R users groaning; I never do this but have a situation I feel it's ok to).

DF <- mtcars
overlap = "> 2"
as.numeric(rowSums(DF[, 1:6]) overlap)

How can I make the third line work like:

as.numeric(rowSums(DF[, 1:6]) > 2)

I know it's likely eval and parse but never use them so don't really understand how to use them here.

Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519

3 Answers3

7

Something like

Olap <- unlist(strsplit( overlap, " "))
Thresh <- as.numeric(Olap[2])
Comp <- match.fun(Olap[1])
Comp(rowSums(DF[,1:6]), Thresh)

An alternative is eval and parse as you suggested

What <- rowSums( DF[,1:6])

 textcall <- sprintf(" What %s", overlap)

 exprcall <- parse(text = textcall)

 eval( exprcall)
mnel
  • 113,303
  • 27
  • 265
  • 254
  • I think you need the `unlist` but this may be the approach I take. Let's see what else the think tank has. – Tyler Rinker Nov 12 '12 at 06:35
  • thanks I was really interested at the start in how to use `eval` `parse` and it's been informative but I think the 1st approach you suggest may be better. +1 I'll give it a bit for people to respond but I already have the function set up using your first suggestion. – Tyler Rinker Nov 12 '12 at 06:47
  • 4 upvotes and no other solutions tell me this is the check mark. I already uploaded the function to github. Works nicely. Thanks for your idea. – Tyler Rinker Nov 12 '12 at 07:24
  • That second option currently does not work. Please remember to correct it when you are in front of a computer :-) Or maybe someone else can? – MattBagg Nov 12 '12 at 08:21
  • @mb3041023 -- The first example is now fixed. The second works for me (unchanged) – mnel Nov 13 '12 at 02:35
  • Me too. That'll teach me to try coding so long after my bed time. Sorry about that. – MattBagg Nov 13 '12 at 03:15
7

You have to convert the entire expression to a string, then convert the parsed text to an expression. Finally, call eval() on the expression.

eg:

overlap <- "> 2"

# Convert to string
exprAsString <- paste0("as.numeric(rowSums(DF[, 1:6]) ", overlap, ")")

# Convert to expression, using parse
expr <- as.expression(parse(text=exprAsString))

# Then call eval()
eval(expr)

Confirming It Works:

identical(eval(expr), as.numeric(rowSums(DF[, 1:6]) > 2))
# [1] TRUE
Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
1

It strikes me that, while @mnel 's solution is good, this is a situation that could be solved by creating a dummy function inside your main function and using your input string (overlap) as an argument to modify body(dummy_function) . That could be a lot cleaner.

Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73