geom_text is my nemesis -- retry

25 views
Skip to first unread message

Stuart Luppescu

unread,
Feb 12, 2015, 10:31:16 AM2/12/15
to ggplot2
My first attempt to post the data didn't work. Trying again.
---------------------------------------------------------------
Hello, Thanks to the wonderful R Graphics Cookbook, I was able to get
this graph to make but I still cant get the annotation I want. I just
want to put the numbers of people below each faceted graph. The code
runs without an error message, but no annotations appear. Under each of
the 3 facets I expect "N=nnn" to be printed but I get nothing.
Here is the main data frame:

structure(list(type = c("elem_iva", "elem_iva", "elem_iva", "elem_iva",
"elem_iva", "elem_iva", "elem_iva", "elem_iva", "elem_sva", "elem_sva",
"elem_sva", "elem_sva", "elem_sva", "elem_sva", "elem_sva", "elem_sva",
"elem_sva", "elem_sva", "hs_pt", "hs_pt", "hs_pt", "hs_pt", "hs_pt",
"hs_pt", "hs_pt", "hs_pt", "hs_pt", "hs_pt", "hs_nopt", "hs_nopt",
"hs_nopt", "hs_nopt", "hs_nopt", "hs_nopt", "hs_nopt", "hs_nopt",
"hs_nopt", "hs_nopt"), cat_diff = structure(c(2L, 3L, 1L, 2L,
3L, 1L, 2L, 3L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 2L, 3L,
1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L,
1L, 2L), .Label = c("Lower", "No Change", "Higher"), class = c("ordered",
"factor")), plain_pct = c(0.615384615384615, 0.384615384615385,
0.00763358778625954, 0.816793893129771, 0.175572519083969, 0.092896174863388,
0.896174863387978, 0.0109289617486339, 0.685714285714286, 0.314285714285714,
0.0151515151515152, 0.813131313131313, 0.171717171717172, 0.0839416058394161,
0.908759124087591, 0.0072992700729927, 0, 1, 0.825396825396825,
0.174603174603175, 0.0769230769230769, 0.822485207100592, 0.100591715976331,
0.258928571428571, 0.732142857142857, 0.00892857142857143, 0.5,
0.5, 0.888888888888889, 0.111111111111111, 0.0975609756097561,
0.780487804878049, 0.121951219512195, 0.233333333333333, 0.733333333333333,
0.0333333333333333, 0.333333333333333, 0.666666666666667), plain_summative_cat = c(1,
1, 2, 2, 2, 3, 3, 3, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 1, 1, 2, 2,
2, 3, 3, 3, 4, 4, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4)), class = "data.frame", .Names = c("type",
"cat_diff", "plain_pct", "plain_summative_cat"), row.names = c(NA,
-38L))

This is the annotation data frame:

structure(list(type = c("elem_iva", "elem_iva", "elem_iva", "elem_sva",
"elem_sva", "elem_sva", "elem_sva", "hs_nopt", "hs_nopt", "hs_nopt",
"hs_nopt", "hs_pt", "hs_pt", "hs_pt", "hs_pt"), plain_summative_cat = structure(c(1L,
2L, 3L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("1",
"2", "3", "4"), class = "factor"), N = c(65, 262, 183, 105, 396,
274, 4, 18, 41, 30, 3, 63, 169, 112, 2)), .Names = c("type",
"plain_summative_cat", "N"), row.names = c(NA, -15L), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), vars = list(type), drop = TRUE)

And here is my code:
ggplot(all_tab3[all_tab3$type=="elem_iva",], aes(x=cat_diff,
y=plain_pct)) +
geom_bar(stat="identity") +
scale_y_continuous(name="Percentage", labels=percent) +
facet_grid(. ~ plain_summative_cat) +
theme(axis.text.x = element_text(angle=90, hjust=1)) +
geom_text(data=all_ns[all_ns$type=="elem_iva",], x=1, y=-.1,
aes(label=paste("N=", N)))

I'm thinking it must be the x location. In the main graph, the bars are
located by cat_diff, which is coded 0, 1, 2. I thought I'd put the
annotation in the middle of the three bars, so I tried to locate the
text at x=1. Doesn't seem to be working. Can anyone give me a bit of
help?

TIA


--
Stuart Luppescu -=-=- slu <AT> ccsr <DOT> uchicago <DOT> edu
CCSR at U of C ,.;-*^*-;., ccsr.uchicago.edu
(^_^)/ 才文と智奈美の父
[Crash programs] fail because they are based on the theory that,
with nine women pregnant, you can get a baby a month.
-- Wernher von Braun


Ben Bond-Lamberty

unread,
Feb 12, 2015, 3:36:21 PM2/12/15
to ggplot2
In the future, please post a fully reproducible example, including any
package dependencies; right now when I try to assign the `all_ns` data
frame in your example it causes an error.

That said, assuming `p` is the graph, this works fine:

test <- expand.grid(cat_diff=c("No
Change","Higher","Lower"),plain_summative_cat=1:3)
p + geom_text(data=test,y=.1,aes(label=paste(cat_diff,"\n",plain_summative_cat)))

I'd guess your annotation data frame need to refer to use No
Change/Higher/Lower, not 0:2.

Ben
> --
> --
> You received this message because you are subscribed to the ggplot2 mailing list.
> Please provide a reproducible example: https://github.com/hadley/devtools/wiki/Reproducibility
>
> To post: email ggp...@googlegroups.com
> To unsubscribe: email ggplot2+u...@googlegroups.com
> More options: http://groups.google.com/group/ggplot2
>
> ---
> You received this message because you are subscribed to the Google Groups "ggplot2" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ggplot2+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Dennis Murphy

unread,
Feb 12, 2015, 3:38:31 PM2/12/15
to Stuart Luppescu, ggplot2
Hi:

all_tab3 was fine, but I still got the error "object 'type' not found"
when trying to read in all_ns. Since it was pretty small, I just
cobbled it by hand.

Unlike most programming languages, R starts indexing at 1 rather than
0, so the integer code associated with 'No change' is 2. I made a
couple of other cosmetic changes, the most important of which was
extending the y-limits a bit to accommodate the labels under the bar
charts. This worked for me:

# <all_tab3 was read in from the previous post into the console>

all_ns <- data.frame(type = c("elem_iva", "elem_iva", "elem_iva", "elem_sva",
"elem_sva", "elem_sva", "elem_sva", "hs_nopt", "hs_nopt", "hs_nopt",
"hs_nopt", "hs_pt", "hs_pt", "hs_pt", "hs_pt"),
plain_summative_cat = c(1L,
2L, 3L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L),
N = c(65, 262, 183, 105, 396,
274, 4, 18, 41, 30, 3, 63, 169, 112, 2))

library("ggplot2")
library("scales") # needed for labels = percent in the scale function

ggplot(subset(all_tab3, type == "elem_iva"), ) +
geom_bar(aes(x=cat_diff, y=plain_pct), stat="identity") +
scale_y_continuous(name="Percentage", labels=percent,
limits = c(-0.05, 1)) +
facet_wrap( ~ plain_summative_cat, nrow = 1) +
theme(axis.text.x = element_text(angle=90, vjust=0.25)) +
geom_text(data = subset(all_ns, type == "elem_iva"),
x = 2, y = -0.025, aes(label = paste("N =", N)),
size = 5)

I should also mention that because you want to use different x and y
variables from different data frames, it's better to avoid mapping x
and y in ggplot() and instead make the aesthetic mappings inside each
geom call.

To extend it to the entire data frame, here is one way:

ggplot(all_tab3) +
geom_bar(aes(x=cat_diff, y=plain_pct), stat="identity") +
scale_y_continuous(name="Percentage", labels=percent,
limits = c(-0.1, 1)) +
facet_grid(type ~ plain_summative_cat) +
theme(axis.text.x = element_text(angle=90, vjust=0.25)) +
geom_text(data = all_ns,
x = 2, y = -0.05, aes(label = paste("N =", N)),
size = 4)


Dennis

Stuart Luppescu

unread,
Feb 12, 2015, 5:10:59 PM2/12/15
to Dennis Murphy, ggplot2
On Thu, 2015-02-12 at 12:38 -0800, Dennis Murphy wrote:
> I should also mention that because you want to use different x and y
> variables from different data frames, it's better to avoid mapping x
> and y in ggplot() and instead make the aesthetic mappings inside each
> geom call.
>
> To extend it to the entire data frame, here is one way:
>
> ggplot(all_tab3) +
> geom_bar(aes(x=cat_diff, y=plain_pct), stat="identity") +
> scale_y_continuous(name="Percentage", labels=percent,
> limits = c(-0.1, 1)) +
> facet_grid(type ~ plain_summative_cat) +
> theme(axis.text.x = element_text(angle=90, vjust=0.25)) +
> geom_text(data = all_ns,
> x = 2, y = -0.05, aes(label = paste("N =", N)),
> size = 4)

Perfect. Thanks very much, Dennis. I was not aware of the issue with
aes() with two different data frames.

Dennis Murphy

unread,
Feb 12, 2015, 10:14:27 PM2/12/15
to Stuart Luppescu, ggplot2
The idea is this: when you define a data frame and a set of mapped
aesthetics in ggplot(), each subsequent layer 'inherits' the data
frame and mapped aesthetics unless overridden in a geom or stat call.
When using multiple data frames to construct a ggplot with different
sets of aesthetics in different layers, it's sometimes better to
specify only what will be common to all layers in ggplot().

In your case, you were mapping x and y in the geom_bar() layer but
setting them in the geom_text() layer; moreover, the mapped aesthetic
in geom_text() [label] is not understood by geom_bar(), so it makes
some sense in that context to map aesthetics within layer.


Dennis
Reply all
Reply to author
Forward
0 new messages