24

I would like to convert a string that I pass in a function into an object (or column name).

I know that this works:

df <- data.frame(A = 1:10, B = 11:20)

test.function <- function(x)            
{
  z <- df[[x]]
  return(z)
}
test.function("A")

I don't want to use the [[.]] operator, because sometimes it is unpractical or even not applicable. I am interessted in a general method to convert a string into an "object". Therefore I tried the following:

df <- data.frame(A = 1:10, B = 11:20)

test.function <- function(x)
{
  z <- get(paste("df$", x, sep = ""))
  return(z)
}
test.function("A")

or

df <- data.frame(A = 1:10, B = 11:20)

test.function <- function(x)
{
  z <- as.name(paste("df$", x, sep = ""))
  return(z)
}
test.function("A")

or

df <- data.frame(A = 1:10, B = 11:20)

test.function <- function(x)
{
  z <- df$as.name(x)
  return(z)
}
test.function("A")

I also tried to play around with the parse, do.call and eval functions. Unfortunatelly I failed

5 Answers 5

34

The trick is to use parse. For instance:

> x <- "A"
> eval(parse(text=paste("df$", x, sep = "")))
 [1]  1  2  3  4  5  6  7  8  9 10

See also this Q/A: Evaluate expression given as a string

Sign up to request clarification or add additional context in comments.

2 Comments

If the answer is parse() you should usually rethink the question. —Thomas Lumley R-help (February 2005) -- PS, i upvoted because I can't think of a better way either :)
@JDLong Yea regular indexing by column name with [ is always sufficient for me. Then you can take one column, or 2, or whatever...
7

I just got an upvote which brought me back after 5 years to this question. I still think that the correct answer is [[ despite the OP's request not to use it, but here's a way to dress up [[ as a more functional "function".

df <-     structure(list(x = 1:3, y = 1:3), .Names = c("x", "y"), row.names = c(NA, 
-3L), class = "data.frame")

 test.function <- `[[`    # So simple, `test.function` now has all the features desired.
 df
 x y
 1 1
 2 2
 3 3
 test.function(df, "x")
#[1] 1 2 3

Or if it were desireable to hard code pulling an object named 'df' from the calling environment, a proposition that seems of dubious safety:

 test.df_txt <- function(var, dfn ='df' ){ get(dfn)[[var]] }
 test.df_txt("x")
#[1] 1 2 3

Original response (still not recommended):

You can sidestep around the limitations of "$" if you are willing to use eval(parse(text=...)) :

 test.function <- function(x)  {
   z <- eval(parse( text=paste("df$", x, sep = "")), env=.GlobalEnv)
   return(z)
   }
test.function("A")
# [1]  1  2  3  4  5  6  7  8  9 10

BUT ... it is much better to use "[[". (My initial efforts at eval(parse()-ing were stuck at not knowing enough to use the "text" argument to parse.)

Comments

5

In addition to eval(parse(text=YOUR_STRING)), you can use as.symbol as a potential alternative.

1 Comment

Yes, eval(as.symbol(YOUR_STRING)) worked for me. Thank you.
1

You can create a variable name from a string using the assign operator, as in: assign("a_string", NULL)

Comments

1

The function call nicely does what you want like this:

x <- data.frame(a = c(TRUE, FALSE, NA), b = 1:9, c = dnorm(-4:4), d = exp(-4:4 * 1i), `syntaxically invalid name` = LETTERS[1:9], check.names = FALSE)


solution <- function (string)
eval(call(name = "$", quote(x), as.symbol(string)))


print(solution("a"))
print(solution("syntaxically invalid name"))

If you wanted to be able to specify the name of the object you're retrieving the column from, try:

x <- data.frame(a = c(TRUE, FALSE, NA), b = 1:9, c = dnorm(-4:4), d = exp(-4:4 * 1i), `syntaxically invalid name` = LETTERS[1:9], check.names = FALSE)
y <- x
y$b <- y$b * 2L


solution <- function (object.name, string)
eval(call(name = "$", as.symbol(object.name), as.symbol(string)))


print(solution("x", "b"))
print(solution("y", "b"))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.