sinclairjesse
sinclairjesse

Reputation: 1595

Express a string as a function in R

I am automating the creation of a series of plots each of which is based on a class of chemicals (e.g., metals, PCBs, etc.); for reasons I'll leave out, I am plotting the legend outside of the plot and using negative values for the inset argument for the legend() function to do this (e.g., inset = c(-0.2, 0)). As each of the chemical classes requires different values for the inset I thought of creating a hash table using the hash package to store the values needed for each chemical class. However, in order to store these in the hash table I was storing the vector of values as a string (e.g., "c(-0.2, 0)").

My code for the hash table looks like this: legend.hash <- hash(chem.class, c('c(-0.2, 0)', 'c(-0.2, 0)', 'c(-0.25, -0.4)', 'c(-0.25, -0.3)', 'c(-0.2, 0)', 'c(-0.4, -0.2)', 'c(-0.2, 0)', 'c(-0.2, 0)')) where chem.class is a vector of chemical classes.

Retrieving the values from the resulting hash table are obviously as a string "c(-0.2, 0)", is there a way of converting this string of text so that R interprets it as a function that could be used like the following: legend(..., inset = legend.hash[[chem.class[i]]])?

Or is there a better way to implement this using the traditional graphics system?

Upvotes: 3

Views: 349

Answers (3)

Greg Snow
Greg Snow

Reputation: 49680

If you really want to convert a string with 2 number values in it into a vector of numbers then consider using the strapply function from the gsubfn package. This way you avoid the parse function and all the potential headaches that come with it. It may also end up being faster.

If you change the strings to just the numbers and a seperator (without the 'c' and parens) then you could just use as.numeric on the result of strsplit which may be even faster.

Upvotes: 1

Greg Snow
Greg Snow

Reputation: 49680

It may work better to position your legend using the grconvertX and grconvertY functions rather than using negative insets.

Upvotes: 1

Joris Meys
Joris Meys

Reputation: 108633

The classic way of executing a string as if it was a function is by using eval() and parse() :

> eval(parse(text="c(-0.2,0)"))
[1] -0.2  0.0

But I really wonder why you insist on using a hash instead of a simple list.

 legend.hash <- list(c(-0.2, 0), c(-0.2, 0), c(-0.25, -0.4), c(-0.25, -0.3), 
                 c(-0.2, 0), c(-0.4, -0.2), c(-0.2, 0), c(-0.2, 0))
 names(legend.hash) <- chem.class

would allow you to use the exact construct you're using now, without all the tricky bits and pieces of eval() and parse(), especially thinking about the infamous fortune(106) :

> require(fortunes)
> fortune(106)

If the answer is parse() you should usually rethink the question.
   -- Thomas Lumley
      R-help (February 2005)

Upvotes: 7

Related Questions