Skip to content

use ggplot in a function to which a column name is given

5 messages · jiho, Hadley Wickham

#
Hi everyone, Hi ggplot users in particular,

ggplot makes it very easy to plot things given their names when you  
use it interactively (and therefore can provide the names of the  
columns).
	qplot(x,foo,data=A) where A has columns (x,y,foo,bar) for example

but I would like to use this from inside a function to which the name  
of the column is given. I cannot find an elegant way to make this  
work. Here are my attempts:

#------------------------------------------------------------

library(ggplot2)

A = data.frame(x=rep(1:10,10), y=rep(1:10,each=10), u=runif(100),  
v=rnorm(100))

# goal: extract values for y<=5 and plot them, either for u or v

foo1 <- function(uv="u")
{
	# solution 1: do not use the data argument at all
	# 	(forces the use of qplot, could be more elegant)
	B = A[A$y<=5,]
	qplot(B$x, B$y, fill=B[[uv]], geom="tile")
}

foo2 <- function(uv="u")
{
	# solution 2: extract and rename the colums, then use the data argument
	# 	(enables ggplot but could be shorter)
	B = A[A$y<=5,c("x","y",uv)]
	names(B)[3] = "value"
	# rem: cannot use rename since rename(B,c(uv="value")) would not work
	qplot(x, y, fill=value, data=B, geom="tile")
	# or
	# ggplot(B,aes(x=x,y=y,fill=value)) + geom_tile()
}

foo3 <- function(uv="u")
{
	# solution 3: use the data argument and perform the extraction  
directly in it
	#	(elegant and powerful but can't make it work)
	ggplot(A[A$y<=5,c("x","y",uv)],aes(x=x,y=y,fill=???)) + geom_tile()
	# or
	ggplot(A[A$y<=5,],aes(x=x,y=y,fill=???)) + geom_tile()
	# or ...	
}

print(foo1("u"))
print(foo1("v"))
print(foo2("u"))
print(foo3("u"))

#------------------------------------------------------------

Any help in making foo3 work would be appreciated. Thanks in advance  
for your expertise.

JiHO
---
http://jo.irisson.free.fr/
#
Follow up.
On 2007-December-13 , at 10:45 , jiho wrote:
---> actually this does not even work currently:
	Error in eval(expr, envir, enclos) : object "B" not found
Which only leaves the most inelegant solution: 2

JiHO
---
http://jo.irisson.free.fr/
#
Hi Jiho,

The key to solving this problem is to use aes_string instead of aes.
Instead of the complicated munging that aes does to get the names of
the variables, aes_string works directly with strings, so that:

aes_string(x = "mpg", y = "wt") == aes(x = mpg, y = wt)

So your function would look like:

foo4 <- function(uv="u") {
  ggplot(A, aes_string(x = "x", y= "y", fill = uv)) + geom_tile()
}

Or

ggplot(A, aes(x=x, y=y)) + aes_string(fill=uv) + geom_tile()

Hope that helps!  (And I've made a note to better document aes_string
so you can discover after looking at aes)

Hadley
On 12/13/07, jiho <jo.irisson at gmail.com> wrote:

  
    
#
On 2007-December-13 , at 15:56 , hadley wickham wrote:
great! I knew you would have thought this through. That's perfect. As  
always there's the trade-off between writing code and documenting the  
code already written. In this case the trade-off turned toward the  
code part I guess.

Autodetection of strings by aes would be even greater but that would  
prevent me to assign the actual strings "u", "x", "y" to an aes  
element, which I don't see as a problem for non text related functions  
though...

Thanks again.

JiHO
---
http://jo.irisson.free.fr/
#
It can come in handy when combining multiple datasets:

mtcarsq <- as.data.frame(mtcars ^ 2)

ggplot(mtcars, aes(x=mpg, y=wt)) + geom_point(aes(colour = "Raw")) +
geom_point(aes(colour="Squared"), data=mtcarsq)

and aes is complicated enough as it is.

Hadley