How to access external variable for label in geom_text ?

2,372 views
Skip to first unread message

Mauricio

unread,
Mar 26, 2011, 5:03:49 PM3/26/11
to ggplot2
Hi,

For some reason, I get an error when trying supply a variable to
'label' in the aes mappings of geom_text.

I'm following an example from pg 87 of the ggplot2 book. There a
variable 'caption' holds a string, which is used in the subsequent
line of code ... + geom_text(aes(x, y, label=caption), ...

The structure of my code is the same. When I run it (from inside a
function), R gives "Error in eval(expr, envir, enclos) : object
'caption' not found".

What could be causing this?

Brandon Hurr

unread,
Mar 26, 2011, 6:35:06 PM3/26/11
to Mauricio, ggplot2
It's hard to say without much context and without the book in front of me, but I remember this happening a lot when I was using ggplot() inside of functions and things. 

aes_string instead of aes() seemed to fix some of it. Have you tried using that?

using your example: 

+ geom_text(aes_string("x", "y", label="caption")


HTH, 
B


--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: http://gist.github.com/270442

To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

Mauricio

unread,
Mar 27, 2011, 6:46:31 PM3/27/11
to ggplot2
Brandon,

Thanks for the suggestion. I tried it ... using aes_string did not
work.

However, I discovered that if I create the caption variable prior to
calling the function that constructs my plot, then everything
(original code) works OK. Perhaps what I need to do in the function
is to set the caption variable in the calling environment. I think
this would be the equivalent of creating the variable prior to calling
the function.

Mauricio

Mauricio

unread,
Mar 27, 2011, 8:03:41 PM3/27/11
to ggplot2, brando...@gmail.com
I went ahead and caused the plotting function to set a caption
variable in the global environment. That worked ... the aes function
insided geom_text had no problem with that. Unfortunately this is not
a nice solution since I could accidentally clobber a pre-existing
variable.

I also tried a different approach. The main function sets the caption
variable, then the plotting is done by calling a nested function. I
figured this way the aes function would look in the parent environment
for the caption variable. This did not work. That's unfortunate, it
would have been much cleaner. Perhaps there's a way to force looking
in the parent environment and not just in the global one.

Thanks for your thoughts,
Mauricio

Brian Diggs

unread,
Mar 28, 2011, 3:10:48 PM3/28/11
to Mauricio, ggplot2
On 3/27/2011 5:03 PM, Mauricio wrote:
> I went ahead and caused the plotting function to set a caption
> variable in the global environment. That worked ... the aes function
> insided geom_text had no problem with that. Unfortunately this is not
> a nice solution since I could accidentally clobber a pre-existing
> variable.

The caption variable needs to be a column in the data.frame that you are
passing to ggplot, not a free variable. When you said you created it in
the global environment, I got the impression it was a separate variable,
not part of the data.frame.

> I also tried a different approach. The main function sets the caption
> variable, then the plotting is done by calling a nested function. I
> figured this way the aes function would look in the parent environment
> for the caption variable. This did not work. That's unfortunate, it
> would have been much cleaner. Perhaps there's a way to force looking
> in the parent environment and not just in the global one.
>
> Thanks for your thoughts,
> Mauricio
>
> On Mar 27, 6:46 pm, Mauricio<MauricioCorn...@yahoo.com> wrote:
>> Brandon,
>>
>> Thanks for the suggestion. I tried it ... using aes_string did not
>> work.
>>
>> However, I discovered that if I create the caption variable prior to
>> calling the function that constructs my plot, then everything
>> (original code) works OK. Perhaps what I need to do in the function
>> is to set the caption variable in the calling environment. I think
>> this would be the equivalent of creating the variable prior to calling
>> the function.
>>
>> Mauricio
>

--
Brian S. Diggs, PhD
Senior Research Associate, Department of Surgery
Oregon Health & Science University

Mauricio

unread,
Mar 28, 2011, 4:05:43 PM3/28/11
to ggplot2

> The caption variable needs to be a column in the data.frame that you are
> passing to ggplot, not a free variable.  When you said you created it in
> the global environment, I got the impression it was a separate variable,
> not part of the data.frame.

Brian, thanks for the suggestion. I tried it, didn't work. Got
original error about the variable not being found.

I think may be be fundamentally misunderstanding geom_text. For
example, I don't understand the difference between the data supplied
to ggplot and that that supplied to geom_text. I assume that the data
passed to geom_text is a second data frame that specifies coordinates
of label position(s).

My code is below. It implements your suggestion. All I'm trying to
do is print one label that displays the number of observations. R
chokes on 2nd-to-last line with: "Object 'caption' not found."

myplot <- function() {

library(ggplot2)
bins <- c(0.1,0.25,0.5,1,2,3,5)
bincounts <- c(51,28,21,10,15,1,1)
counts <- data.frame(bin=factor(bins,ordered=TRUE),
bincount=bincounts) #Joint two vectors into dataframe.
counts$caption <- NA
counts$caption[1] <- paste("N = ", sum(counts$bincount))
p <- ggplot(data=counts, aes(x=bin,y=bincount)) + geom_bar()
p <- p + geom_text(aes(x,y,label=caption),
data=data.frame(x=nrow(counts)-1,y=30))
p
}

Many thanks,
Mauricio

Ista Zahn

unread,
Mar 28, 2011, 4:19:58 PM3/28/11
to Mauricio, ggplot2
Hi Mauricio,

On Mon, Mar 28, 2011 at 4:05 PM, Mauricio <Maurici...@yahoo.com> wrote:
>
>> The caption variable needs to be a column in the data.frame that you are
>> passing to ggplot, not a free variable.  When you said you created it in
>> the global environment, I got the impression it was a separate variable,
>> not part of the data.frame.
>
> Brian,  thanks for the suggestion.  I tried it, didn't work.  Got
> original error about the variable not being found.
>
> I think may be be fundamentally misunderstanding geom_text.  For
> example, I don't understand the difference between the data supplied
> to ggplot and that that supplied to geom_text.  I assume that the data
> passed to geom_text is a second data frame that specifies coordinates
> of label position(s).

And the labels! If you look at the data you pass to geom_text, you
will see that indeed it does not include caption:

data.frame(x=nrow(counts)-1,y=30)
x y
1 6 30

>
> My code is below.  It implements your suggestion.  All I'm trying to
> do is print one label that displays the number of observations.  R
> chokes on 2nd-to-last line with: "Object 'caption' not found."
>
> myplot <- function() {
>
>  library(ggplot2)
>  bins <- c(0.1,0.25,0.5,1,2,3,5)
>  bincounts <- c(51,28,21,10,15,1,1)
>  counts <- data.frame(bin=factor(bins,ordered=TRUE),
> bincount=bincounts)  #Joint two vectors into dataframe.
>  counts$caption <- NA
>  counts$caption[1] <- paste("N = ", sum(counts$bincount))
>  p <- ggplot(data=counts, aes(x=bin,y=bincount))  + geom_bar()
>  p <- p + geom_text(aes(x,y,label=caption),
> data=data.frame(x=nrow(counts)-1,y=30))
>  p
> }

I don't think geom_text is the right tool for this. You can make it
work, something like

p <- ggplot(data=counts, aes(x=bin,y=bincount)) + geom_bar()
p <- p + geom_text(aes(x,y,label=caption),

data=data.frame(x=nrow(counts)-1,y=30, caption = paste("N = ",
sum(counts$bincount))))

but you're really abusing the notion of a text geom. What you appear
to be after is an _annotation_:

p <- ggplot(data=counts, aes(x=bin,y=bincount)) +

geom_bar() +
annotate(geom="text", x=nrow(counts)-1, y=30, label = paste("N =
", sum(counts$bincount)))

best,
Ista

>
> Many thanks,
> Mauricio


>
> --
> You received this message because you are subscribed to the ggplot2 mailing list.
> Please provide a reproducible example: http://gist.github.com/270442
>
> To post: email ggp...@googlegroups.com
> To unsubscribe: email ggplot2+u...@googlegroups.com
> More options: http://groups.google.com/group/ggplot2
>

--
Ista Zahn
Graduate student
University of Rochester
Department of Clinical and Social Psychology
http://yourpsyche.org

Brian Diggs

unread,
Mar 28, 2011, 4:25:58 PM3/28/11
to Mauricio, ggplot2

Thanks for the example. I can see what is going wrong. The data.frame
that is being passed to geom_text is the one that must have the caption
variable, not the default (one listed in the ggplot call) one. I didn't
realize you had a data argument to that geom. You could add it directly
to that call, or pull out the data.frame creation before the call:


library("ggplot2")
myplot <- function(x) {


bins <- c(0.1,0.25,0.5,1,2,3,5)
bincounts <- c(51,28,21,10,15,1,1)
counts <- data.frame(bin=factor(bins,ordered=TRUE),
bincount=bincounts) #Joint two vectors into dataframe.

labels <- data.frame(x=nrow(counts)-1,
y=30, caption=paste("N = ", sum(counts$bincount), sep=""))
p <- ggplot(data=counts, aes(x=bin, y=bincount)) +
geom_bar() +
geom_text(data=labels, aes(x=x, y=y, label=caption))
p
}

I pulled out the library call; it doesn't hurt being in the function
call, but it only really needs to be called once.

Another approach, since you are just making a single notation rather
than adding text for each data point, is to use the annotate function
which simplifies the creation of a one-off data.frame and geom call.

myplot <- function(x) {


bins <- c(0.1,0.25,0.5,1,2,3,5)
bincounts <- c(51,28,21,10,15,1,1)
counts <- data.frame(bin=factor(bins,ordered=TRUE),
bincount=bincounts) #Joint two vectors into dataframe.

ggplot(data=counts, aes(x=bin, y=bincount)) +
geom_bar() +
annotate("text", x=nrow(counts)-1, y=30,
label=paste("N = ", sum(counts$bincount), sep=""))
}

> Many thanks,

Mauricio

unread,
Mar 28, 2011, 5:12:27 PM3/28/11
to ggplot2
Ista and Brian,

Thanks for catching the error I was making ... and for suggesting the
use of 'annotate', which was exactly what was needed. Neither the
ggplot2 book nor its author's web site reference manual identifies
this function.

Thanks again,
Mauricio
Reply all
Reply to author
Forward
0 new messages