Getting strings recognized as variable names in R

Related: Strings as variable references in R
Possibly related: Concatenate expressions to subset a dataframe


I've simplified the question per the comment request. Here goes with some example data.

dat <- data.frame(num=1:10,sq=(1:10)^2,cu=(1:10)^3)
set1 <- subset(dat,num>5)
set2 <- subset(dat,num<=5)

Now, I'd like to make a bubble plot from these. I have a more complicated data set with 3+ colors and complicated subsets, but I do something like this:

symbols(set1$sq,set1$cu,circles=set1$num,bg="red")
symbols(set2$sq,set2$cu,circles=set2$num,bg="blue",add=T)

I'd like to do a for loop like this:

colors <- c("red","blue")
sets <- c("set1","set2")
vars <- c("sq","cu","num")


for (i in 1:length(sets)) {
symbols(sets[[i]][,sq],sets[[i]][,cu],circles=sets[[i]][,num],
bg=colors[[i]],add=T)
}

I know you can have a variable evaluated to specify the column (like var="cu"; set1[,var]; I want to know how to get a variable to specify the data.frame itself (and another to evaluate the column).


Update: Ran across this post on r-bloggers which has this example:

x <- 42
eval(parse(text = "x"))
[1] 42

I'm able to do something like this now:

eval(parse(text=paste(set[[1]],"$",var1,sep="")))

In fiddling with this, I'm finding it interesting that the following are not equivalent:

vars <- data.frame("var1","var2")
eval(parse(text=paste(set[[1]],"$",var1,sep="")))
eval(parse(text=paste(set[[1]],"[,vars[[1]]]",sep="")))

I actually have to do this:

eval(parse(text=paste(set[[1]],"[,as.character(vars[[1]])]",sep="")))

Update2: The above works to output values... but not in trying to plot. I can't do:

for (i in 1:length(set)) {
symbols(eval(parse(text=paste(set[[i]],"$",var1,sep=""))),
eval(parse(text=paste(set[[i]],"$",var2,sep=""))),
circles=paste(set[[i]],".","circles",sep=""),
fg="white",bg=colors[[i]],add=T)
}

I get invalid symbol coordinates. I checked the class of set[[1]] and it's a factor. If I do is.numeric(as.numeric(set[[1]])) I get TRUE. Even if I add that above prior to the eval statement, I still get the error. Oddly, though, I can do this:

set.xvars <- as.numeric(eval(parse(text=paste(set[[i]],"$",var1,sep=""))))
set.yvars <- as.numeric(eval(parse(text=paste(set[[i]],"$",var2,sep=""))))
symbols(xvars,yvars,circles=data$var3)

Why different behavior when stored as a variable vs. executed within the symbol function?

156162 次浏览

You found one answer, i.e. eval(parse()) . You can also investigate do.call() which is often simpler to implement. Keep in mind the useful as.name() tool as well, for converting strings to variable names.

Subsetting the data and combining them back is unnecessary. So are loops since those operations are vectorized. From your previous edit, I'm guessing you are doing all of this to make bubble plots. If that is correct, perhaps the example below will help you. If this is way off, I can just delete the answer.

library(ggplot2)
# let's look at the included dataset named trees.
# ?trees for a description
data(trees)
ggplot(trees,aes(Height,Volume)) + geom_point(aes(size=Girth))
# Great, now how do we color the bubbles by groups?
# For this example, I'll divide Volume into three groups: lo, med, high
trees$set[trees$Volume<=22.7]="lo"
trees$set[trees$Volume>22.7 & trees$Volume<=45.4]="med"
trees$set[trees$Volume>45.4]="high"


ggplot(trees,aes(Height,Volume,colour=set)) + geom_point(aes(size=Girth))




# Instead of just circles scaled by Girth, let's also change the symbol
ggplot(trees,aes(Height,Volume,colour=set)) + geom_point(aes(size=Girth,pch=set))


# Now let's choose a specific symbol for each set. Full list of symbols at ?pch
trees$symbol[trees$Volume<=22.7]=1
trees$symbol[trees$Volume>22.7 & trees$Volume<=45.4]=2
trees$symbol[trees$Volume>45.4]=3


ggplot(trees,aes(Height,Volume,colour=set)) + geom_point(aes(size=Girth,pch=symbol))

Without any example data, it really is difficult to know exactly what you are wanting. For instance, I can't at all divine what your object set (or is it sets) looks like.

That said, does the following help at all?

set1 <- data.frame(x = 4:6, y = 6:4, z = c(1, 3, 5))


plot(1:10, type="n")
XX <- "set1"
with(eval(as.symbol(XX)), symbols(x, y, circles = z, add=TRUE))

EDIT:

Now that I see your real task, here is a one-liner that'll do everything you want without requiring any for() loops:

with(dat, symbols(sq, cu, circles = num,
bg = c("red", "blue")[(num>5) + 1]))

The one bit of code that may feel odd is the bit specifying the background color. Try out these two lines to see how it works:

c(TRUE, FALSE) + 1
# [1] 2 1
c("red", "blue")[c(F, F, T, T) + 1]
# [1] "red"  "red"  "blue" "blue"

If you want to use a string as a variable name, you can use assign:

var1="string_name"


assign(var1, c(5,4,5,6,7))


string_name


[1] 5 4 5 6 7

The basic answer to the question in the title is eval(as.symbol(variable_name_as_string)) as Josh O'Brien uses. e.g.

var.name = "x"
assign(var.name, 5)
eval(as.symbol(var.name)) # outputs 5

Or more simply:

get(var.name) # 5

What works best for me is using quote() and eval() together.

For example, let's print each column using a for loop:

Columns <- names(dat)
for (i in 1:ncol(dat)){
dat[, eval(quote(Columns[i]))] %>% print
}