How to plot a combined bar and line plot in ggplot2 - r

I have the following data which I am trying to plot as combined bar and line plot (with CI)
A data frame of Feature, Count, Odds Ratio and Confidence Interval values for OR
I am trying to get a plot as
A bar plot for count over lapped with a line plot for Odds Ratio with CI bars
I tried to plot in ggplot2 using following code:
ggplot(feat)+
geom_bar(aes(x=Feat, y=Count),stat="identity", fill = "steelblue") +
geom_line(aes(x=Feat, y=OR*max(feat$Count)),stat="identity", group = 1) +
geom_point(aes(x=Feat, y=OR*max(feat$Count))) +
geom_errorbar(aes(x=Feat, ymin=CI1, ymax=CI2), width=.1, colour="orange",
position = position_dodge(0.05))
However, I am not getting the CI bars for the line graph, as can be seen in pic: Rather, I am getting them for barplot
Can someone can please help me out to sort this issue.
Thanks
Edit - Dput:
df <- structure(list(Feat = structure(1:8, .Label = c("A", "B", "C",
"D", "E", "F", "G", "H"), class = "factor"), Count = structure(c(2L,
8L, 7L, 5L, 4L, 1L, 6L, 3L), .Label = c("13", "145", "2", "25",
"26", "3", "37", "43"), class = "factor"), OR = structure(c(4L,
2L, 1L, 5L, 3L, 7L, 6L, 8L), .Label = c("0.38", "1.24", "1.33",
"1.51", "1.91", "2.08", "2.27", "3.58"), class = "factor"), CI1 = structure(c(7L,
4L, 1L, 6L, 3L, 5L, 2L, 2L), .Label = c("0.26", "0.43", "0.85",
"0.89", "1.2", "1.24", "1.25"), class = "factor"), CI2 = structure(c(3L,
2L, 1L, 6L, 4L, 7L, 8L, 5L), .Label = c("0.53", "1.7", "1.82",
"1.98", "13.07", "2.83", "3.92", "6.13"), class = "factor")), class = "data.frame", row.names = c(NA,
-8L))

Is this what you had in mind?
ratio <- max(feat$Count)/max(feat$CI2)
ggplot(feat) +
geom_bar(aes(x=Feat, y=Count),stat="identity", fill = "steelblue") +
geom_line(aes(x=Feat, y=OR*ratio),stat="identity", group = 1) +
geom_point(aes(x=Feat, y=OR*ratio)) +
geom_errorbar(aes(x=Feat, ymin=CI1*ratio, ymax=CI2*ratio), width=.1, colour="orange",
position = position_dodge(0.05)) +
scale_y_continuous("Count", sec.axis = sec_axis(~ . / ratio, name = "Odds Ratio"))
Edit: Just for fun with the legend too.
ggplot(feat) +
geom_bar(aes(x=Feat, y=Count, fill = "Count"),stat="identity") + scale_fill_manual(values="steelblue") +
geom_line(aes(x=Feat, y=OR*ratio, color = "Odds Ratio"),stat="identity", group = 1) + scale_color_manual(values="orange") +
geom_point(aes(x=Feat, y=OR*ratio)) +
geom_errorbar(aes(x=Feat, ymin=CI1*ratio, ymax=CI2*ratio), width=.1, colour="orange",
position = position_dodge(0.05)) +
scale_y_continuous("Count", sec.axis = sec_axis(~ . / ratio, name = "Odds Ratio")) +
theme(legend.key=element_blank(), legend.title=element_blank(), legend.box="horizontal",legend.position = "bottom")
Since you asked about adding p values for comparisons in the comments, here is a way you can do that. Unfortunately, because you don't really want to add **all* the comparisons, there's a little bit of hard coding to do.
library(ggplot2)
library(ggsignif)
ggplot(feat,aes(x=Feat, y=Count)) +
geom_bar(aes(fill = "Count"),stat="identity") + scale_fill_manual(values="steelblue") +
geom_line(aes(x=Feat, y=OR*ratio, color = "Odds Ratio"),stat="identity", group = 1) + scale_color_manual(values="orange") +
geom_point(aes(x=Feat, y=OR*ratio)) +
geom_errorbar(aes(x=Feat, ymin=CI1*ratio, ymax=CI2*ratio), width=.1, colour="orange",
position = position_dodge(0.05)) +
scale_y_continuous("Count", sec.axis = sec_axis(~ . / ratio, name = "Odds Ratio")) +
theme(legend.key=element_blank(), legend.title=element_blank(), legend.box="horizontal",legend.position = "bottom") +
geom_signif(comparisons = list(c("A","H"),c("B","F"),c("D","E")),
y_position = c(150,60,40),
annotation = c("***","***","n.s."))

Related

How to replicate three plots next to each other with marginal plot on two of them?

This is what I want to achieve:
I'm trying to replicate the theme of these graph using ggplot, I searched online for articles and question to show me how to assign these plots the right size and position and also to assign the tight dot shape, and I found few articles that discussed changing position, I tried the following:
d1<-read.csv("./data/games.csv")
library(ggplot2)
library(dplyr)
d1 %>%
filter(winner != "draw") %>%
ggplot(aes(x=cream_rating, y=charcoal_rating, color = winner, shape = winner)) +
# Map winner on color. Add some transparency in case of overplotting
geom_point(alpha = 0.2, na.rm = TRUE) +
# Just a guess to add the cross: Add geom_pints with one variable fixed on its mean
# Should "draw"s be colored or dropped?
scale_color_manual(values = c(cream = "seagreen4", charcoal = "chocolate3")) +
scale_shape_manual(values = c(cream = 16, charcoal = 17)) +
ggtitle("Rating of Cream vs Charcoal") +
xlab("rating of cream") + ylab("rating of charcoal")+ theme_classic() + theme(plot.title = element_text(hjust = 0.5))
p.1<-ggplot(d1, aes(x=cream_rating, y=charcoal_rating)) +
# Map winner on color. Add some transparency in case of overplotting
geom_point(aes(color = winner), alpha = 0.2) +
# Add the cross: Add geom_pints with one variable fixed on its mean
geom_point(aes(y = mean(charcoal_rating), color = winner), alpha = 0.2) +
scale_shape_manual(values=c(16, 17)) +
# "draw"s should be dropped and removed from the title
scale_color_manual(values = c(cream = "seagreen4", charcoal = "chocolate3", draw = NA)) +
ggtitle("Rating of Cream vs Charcoal") +
xlab("rating of cream") + ylab("rating of charcoal") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
p.01<-ggplot(d1, aes(x=cream_rating, y=charcoal_rating)) +
# Map winner on color. Add some transparency in case of overplotting
geom_density2d(aes(color = winner), alpha = 0.2) +
# Add the cross: Add geom_pints with one variable fixed on its mean
scale_shape_manual(values=c(16, 17, 0)) +
# "draw"s should be dropped and removed from the title
scale_color_manual(values = c(cream = "seagreen4", charcoal = "chocolate3", draw = "blue")) +
ggtitle("Rating of Cream vs Charcoal") +
xlab("rating of cream") + ylab("rating of charcoal") + theme_classic() + theme(plot.title = element_text(hjust = 0.5))
plot.1<-p.1
plot.02<-ggExtra::ggMarginal(p.01, type = "density",
margins = 'both',
size = 5,
groupColour = TRUE,
groupFill = TRUE
)
plot.02
require(gridExtra)
plot.1<-p.1
plot.2<-ggExtra::ggMarginal(p.1, type = "histogram")
grid.arrange(plot.1, plot.2, ncol=3)
plot.02
library(cowplot)
theme_set(theme_cowplot())
plot.1<-p.1
plot.2<-ggExtra::ggMarginal(p.1, type = "histogram")
plot.02
plot_grid(plot.1, plot.2, plot.02, labels = "AUTO")
cowplot::plot_grid(plot.1, plot.2, plot.02, labels = "AUTO")
library(magrittr)
library(multipanelfigure)
figure1 <- multi_panel_figure(columns = 2, rows = 1, panel_label_type = "none")
# show the layout
figure1
figure1 %<>%
fill_panel(plot.1, column = 1, row = 1) %<>%
fill_panel(plot.2, column = 2, row = 1) %<>%
fill_panel(plot.02, column= 3, row = 1) %<>%
figure1
This is my data set structure:
structure(list(rated = c(FALSE, TRUE, TRUE, TRUE, TRUE, FALSE,
TRUE, FALSE, TRUE, TRUE), turns = c(13L, 16L, 61L, 61L, 95L,
5L, 33L, 9L, 66L, 119L), victory_status = structure(c(3L, 4L,
2L, 2L, 2L, 1L, 4L, 4L, 4L, 2L), .Label = c("draw", "mate", "outoftime",
"resign"), class = "factor"), winner = structure(c(2L, 1L, 2L,
2L, 2L, 3L, 2L, 1L, 1L, 2L), .Label = c("charcoal", "cream",
"draw"), class = "factor"), increment_code = structure(c(3L,
7L, 7L, 5L, 6L, 1L, 1L, 4L, 2L, 1L), .Label = c("10+0", "15+0",
"15+2", "15+30", "20+0", "30+3", "5+10"), class = "factor"),
cream_rating = c(1500L, 1322L, 1496L, 1439L, 1523L, 1250L,
1520L, 1413L, 1439L, 1381L), charcoal_rating = c(1191L, 1261L,
1500L, 1454L, 1469L, 1002L, 1423L, 2108L, 1392L, 1209L)), row.names = c(NA,
10L), class = "data.frame")
Thanks to #Stefan's suggestion (which was great help) in getting me this far.

ggplot2: How can I add the fill legend to the x axis? [duplicate]

This question already has answers here:
Multirow axis labels with nested grouping variables
(7 answers)
Closed 3 years ago.
I programmed this barplot with ggplot2, and it worked just fine.
But it is al little bit too wide, so I would like to delete the fill legend and add it to the x-axis like in this image.
How should I change my code?
Here is the data:
> dput(plot.Subject.means)
structure(list(Mode = structure(c(1L, 1L, 2L, 2L), .Label = c("silent",
"aloud"), class = "factor"), PlausibleFit = structure(c(1L, 2L,
1L, 2L), .Label = c("plausible", "implausible"), class = "factor"),
Stimulus = structure(c(2L, 2L, 2L, 2L), .Label = c("fist sent",
"second sent"), class = "factor"), Mean = c(241.743191964286,
258.42306547619, 304.836607142857, 333.330133928571), SE =
c(10.7086547532698,
12.5941104184202, 14.3157931004567, 17.5915009397571)), class =
"data.frame", row.names = c(NA,
-4L))
And the code for the figure
library(ggplot2)
Fig1.GD = ggplot(plot.Subject.means,
aes(x = Mode, y = Mean, fill = PlausibleFit)) +
geom_bar(stat = 'identity', position = 'dodge') +
geom_errorbar(aes(ymin = Mean - SE, ymax = Mean + SE),
width = .2, position = position_dodge(.9)) +
coord_cartesian(ylim = c(100, 400)) +
labs(title = "Gaze Duration Adults") +
xlab("Reading Mode") + ylab("Gaze Duration in ms") +
guides(fill = guide_legend(title = NULL))
Fig1.GD
I don't know about a way to produce your plot exactly, but you could either try to move the legend:
a <- structure(list(Mode = structure(c(1L, 1L, 2L, 2L), .Label = c("silent",
"aloud"), class = "factor"), PlausibleFit = structure(c(1L, 2L,
1L, 2L), .Label = c("plausible", "implausible"), class = "factor"),
Stimulus = structure(c(2L, 2L, 2L, 2L), .Label = c("fist sent",
"second sent"), class = "factor"), Mean = c(241.743191964286,
258.42306547619, 304.836607142857, 333.330133928571), SE =
c(10.7086547532698,
12.5941104184202, 14.3157931004567, 17.5915009397571)), class =
"data.frame", row.names = c(NA,
-4L))
library(ggplot2)
#> Registered S3 methods overwritten by 'ggplot2':
#> method from
#> [.quosures rlang
#> c.quosures rlang
#> print.quosures rlang
Fig1.GD = ggplot(a, aes(x=Mode, y=Mean,
fill=PlausibleFit))+
geom_bar(stat='identity', position='dodge')+
geom_errorbar(aes(ymin=Mean-SE, ymax=Mean+SE),
width=.2,position=position_dodge(.9))+
coord_cartesian(ylim= c(100,400)) +
labs(title="Gaze Duration Adults")+
ylab("Gaze Duration in ms")+
xlab("Reading Mode")+
guides(fill=guide_legend(title=NULL)) +
theme(legend.position = 'bottom')
Fig1.GD
Or add annotations to the plot:
Fig1.GD = ggplot(a, aes(x=Mode, y=Mean,
fill=PlausibleFit))+
geom_bar(stat='identity', position='dodge')+
geom_errorbar(aes(ymin=Mean-SE, ymax=Mean+SE),
width=.2,position=position_dodge(.9))+
coord_cartesian(ylim= c(100,400)) +
labs(title="Gaze Duration Adults")+
ylab("Gaze Duration in ms")+
guides(fill=guide_legend(title=NULL)) +
theme(legend.position = 'none')+
annotate(geom = 'text', x = c(.78,1.22,1.78,2.22),label = a$PlausibleFit, y = 100, color = 'white')
Fig1.GD

how can I plot a complex data structure

I have a data way much bigger than this representative one
df<- structure(list(Pama1 = structure(c(2L, 5L, 3L, 5L, 3L, 3L, 3L,
3L, 3L, 4L, 1L), .Label = c("", "DD1", "n/a", "PAMANA", "zf"), class = "factor"),
X = structure(c(11L, 3L, 10L, 2L, 4L, 5L, 6L, 7L, 8L, 9L,
1L), .Label = c("", "116", "12", "138", "197", "219", "224",
"230", "280", "85", "Start1"), class = "factor"), X.1 = structure(c(11L,
10L, 2L, 4L, 3L, 5L, 8L, 6L, 7L, 9L, 1L), .Label = c("",
"101", "145", "199", "222", "227", "233", "238", "331", "89",
"End1"), class = "factor"), Pama2 = structure(c(2L, 4L, 4L,
4L, 3L, 4L, 4L, 6L, 5L, 1L, 1L), .Label = c("", "DD2", "GGTR",
"n/a", "PAMANA", "T_reg"), class = "factor"), X.2 = structure(c(9L,
2L, 2L, 8L, 3L, 4L, 5L, 6L, 7L, 1L, 1L), .Label = c("", "1",
"115", "208", "214", "232", "376", "85", "Start2"), class = "factor"),
X.3 = structure(c(10L, 8L, 2L, 9L, 3L, 4L, 5L, 6L, 7L, 1L,
1L), .Label = c("", "15", "195", "229", "231", "362", "577",
"76", "86", "End2"), class = "factor"), Pama3 = structure(c(1L,
3L, 3L, 3L, 2L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("DD3",
"GGTR", "n/a"), class = "factor"), X.4 = structure(c(10L,
1L, 7L, 8L, 9L, 9L, 2L, 3L, 4L, 5L, 6L), .Label = c("1",
"129", "136", "153", "166", "178", "48", "65", "66", "Start1"
), class = "factor"), X.5 = structure(c(10L, 6L, 7L, 8L,
3L, 9L, 1L, 2L, 4L, 4L, 5L), .Label = c("131", "138", "144",
"168", "180", "34", "51", "70", "79", "End2"), class = "factor")), .Names = c("Pama1",
"X", "X.1", "Pama2", "X.2", "X.3", "Pama3", "X.4", "X.5"), class = "data.frame", row.names = c(NA,
-11L))
At first I put all starts and ends together and find the range
In this example it is 1 to 577
Then I want to plot or highlight the regions that there is a string
for example, something like this figure that I made
or even like this
The code below tidies up the data into a form suitable for plotting and then uses geom_segment to lay out the sequences. To tidy the data, we want each column to be a variable and each row to be an observation.
library(tidyverse)
## Clean up data frame and convert to long form
df = map_df(seq(1,ncol(df),3), # Turn each group of three columns into separate data frames that we'll stack into long format
~ setNames(df[-1,.x:(.x+2)], c("DD","Start","End")), # Column names appear to be in the first data row, so we'll remove this row and provide new column names
.id="Pama") %>% # This line and next add a "Pama" column
mutate(Pama = paste0("Pama", Pama)) %>%
filter(!DD %in% c("n/a","")) %>% # Remove empty rows
mutate_at(vars(matches("^[SE]")), funs(as.numeric(as.character(.)))) # All columns are in character format. Convert the numbers to numeric format.
The data frame now looks like this:
Pama DD Start End
<chr> <chr> <dbl> <dbl>
1 Pama1 zf 12 89
2 Pama1 zf 116 199
3 Pama1 PAMANA 280 331
4 Pama2 GGTR 115 195
5 Pama2 T_reg 232 362
6 Pama2 PAMANA 376 577
7 Pama3 GGTR 66 144
ggplot(df, aes(y=Pama, yend=Pama)) +
geom_segment(data=data.frame(Pama=unique(df$Pama), x=min(df$Start), xend=max(df$End)),
aes(x=x, xend=xend), colour="grey80", size=10) +
geom_segment(aes(x=Start, xend=End, colour=DD), size=20) +
geom_text(aes(x=(Start+End)/2, label=DD), colour="white", size=3, fontface="bold") +
geom_text(data=gather(df, key, value, Start:End),
aes(x=value, label=value, colour=DD), size=2.5,
fontface="bold", position=position_nudge(0,-0.3)) +
guides(colour=FALSE) +
scale_x_continuous(breaks=seq(0,1000,100)) +
labs(x="", y="") +
theme_classic(base_size=15) +
theme(axis.line.y=element_blank(),
axis.ticks.y=element_blank())
UPDATE: To address your comment, here's another way of positioning the numbers to avoid overlap.
ggplot(df, aes(y=Pama, yend=Pama)) +
geom_segment(data=data.frame(Pama=unique(df$Pama), x=min(df$Start), xend=max(df$End)),
aes(x=x, xend=xend), colour="grey80", size=10) +
geom_segment(aes(x=Start, xend=End, colour=DD), size=20) +
geom_text(aes(x=(Start+End)/2, label=DD), colour="white", size=3, fontface="bold") +
geom_text(data=gather(df, key, value, Start:End),
aes(x=ifelse(key=="Start", value + 10, value - 10), label=value),
colour="white", size=2.8, fontface="bold", position=position_nudge(0,-0.2)) +
guides(colour=FALSE) +
scale_x_continuous(breaks=seq(0,1000,100)) +
labs(x="", y="") +
theme_classic(base_size=15) +
theme(axis.line.y=element_blank(),
axis.ticks.y=element_blank())
UPDATE 2: To address your second comment, we'll add a grouping column that we'll use to alternate high and low number labels:
# Add grouping variable to alternate high and low labels
df = df %>% group_by(Pama) %>% arrange(Start) %>%
mutate(hilow = rep(c("high","low"),nrow(df))[1:n()])
ggplot(df, aes(y=Pama, yend=Pama)) +
geom_segment(data=data.frame(Pama=unique(df$Pama), x=min(df$Start), xend=max(df$End)),
aes(x=x, xend=xend), colour="grey80", size=10) +
geom_segment(aes(x=Start, xend=End, colour=DD), size=20) +
geom_text(aes(x=(Start+End)/2, label=DD), colour="white", size=3, fontface="bold") +
geom_text(data=gather(df, key, value, Start:End) %>% filter(hilow=="high"),
aes(x=value, label=value, colour=DD), hjust=0.5,
size=3, fontface="bold", position=position_nudge(0,0.3)) +
geom_text(data=gather(df, key, value, Start:End) %>% filter(hilow=="low"),
aes(x=value, label=value, colour=DD), hjust=0.5,
size=3, fontface="bold", position=position_nudge(0,-0.3)) +
guides(colour=FALSE) +
scale_x_continuous(breaks=seq(0,1000,100)) +
labs(x="", y="") +
theme_classic(base_size=15) +
theme(axis.line.y=element_blank(),
axis.ticks.y=element_blank())
That is one weird data structure you have. This will probably work out better down the line if you can modify the source data in some way to obtain a tidy dataframe from the start, where each column is a single variable and each row is an observation.
We can wrangle the data to obtain such dataframe (this is in base R, you can arguably achieve the same in other ways, also using dplyr or data.table):
df2 <- rbind(setNames(cbind(rep('DD1', nrow(df) - 1), df[2:nrow(df), 1:3]), c('DD', 'Pama', 'Start', 'End')),
setNames(cbind(rep('DD2', nrow(df) - 1), df[2:nrow(df), 4:6]), c('DD', 'Pama', 'Start', 'End')),
setNames(cbind(rep('DD3', nrow(df) - 1), df[2:nrow(df), 7:9]), c('DD', 'Pama', 'Start', 'End'))
)
df2$Start <- as.numeric(as.character(df2$Start))
df2$End <- as.numeric(as.character(df2$End))
df2 <- df2[!df2$Pama %in% c('','n/a'), ]
df2
#> DD Pama Start End
#> 2 DD1 zf 12 89
#> 4 DD1 zf 116 199
#> 10 DD1 PAMANA 280 331
#> 51 DD2 GGTR 115 195
#> 81 DD2 T_reg 232 362
#> 91 DD2 PAMANA 376 577
#> 52 DD3 GGTR 66 144
This gives us a nice dataset, where we can map any ggplot2's aestethic to a simple column:
library(ggplot2)
ggplot(df2, aes(y = DD, color = Pama)) +
geom_segment(aes(x = Start, xend = End, yend = DD), size = 10) +
geom_text(aes(label = Start, x = Start), size = 2.5, nudge_y = -.15) +
geom_text(aes(label = End, x = End), size = 2.5, nudge_y = -.15) +
scale_y_discrete(position = 'right') +
theme(panel.background = element_rect(fill = 'white'),
axis.text.x = element_blank(),
axis.text.y.right = element_text(size = 14),
axis.ticks.y = element_blank(),
axis.title = element_blank())
Update:
The text positioning can indeed cause problems, it does so in this example, where we had to reduce the text size to get it somewhat right.
Here is a solution, based on the ggrepel package:
library(ggplot2)
library(ggrepel)
ggplot(df2, aes(y = DD, color = Pama)) +
geom_segment(aes(x = Start, xend = End, yend = DD), size = 10) +
geom_text_repel(data = function(d) tidyr::gather(d, k, p, -DD, -Pama), aes(label = p, x = p), size = 5, nudge_y = -.15, segment.size = 0) +
# geom_label_repel(aes(label = End, x = End), size = 5, nudge_y = -.15) +
geom_text(aes(x = (Start + End) / 2, label = Pama), colour = "white", size = 2.5) +
scale_y_discrete(position = 'right') +
guides(color = FALSE) +
theme(panel.background = element_rect(fill = 'white'),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y.right = element_text(size = 14),
axis.ticks.y = element_blank(),
axis.title = element_blank())
(The text size is forcibly increased to show it does not overlap)
PS: Yea, this update makes it even more similar to #eipi10 answer.. it's a great answer, of course I'd steal from him :P

How to organize percentage values on top of a stacked bar chart ggplot2

I have a very skewed bar chart in ggplot2.
Here's the dput text output:
structure(list(Name = structure(c(1L, 3L, 4L, 5L, 6L, 2L, 1L,
3L, 4L, 5L, 6L, 2L), .Label = c("A", "Average", "B", "C", "D",
"E"), class = "factor"), variable = structure(c(1L, 1L, 1L, 1L,
1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Undiscounted", "Discounted"
), class = "factor"), value = c(18453601.4400001, 11941354.11,
10748756.04, 6488253.74000001, 6078914.73000002, 2509377.50173653,
1157538776.56, 833907589.89, 674006380.96, 574466340.26, 534854603.27,
13191411.5509581)), row.names = c(NA, -12L), .Names = c("Name",
"variable", "value"), class = "data.frame")
Here's the code I use to plot it:
library(ggplot2)
text_size= 18
label_bottom_size=18
plot1<- ggplot(df1, aes(x = Name, y = value, fill = variable)) +
geom_bar(stat = "identity")+
ggtitle(sprintf("Bar chart of Stuff" ))+
theme(axis.title=element_text(size=text_size))+
theme(plot.title=element_text(size=text_size+20))+
theme(axis.text.x= element_text(size=label_bottom_size))+
theme(axis.text.y= element_text(size=text_size))+
theme(legend.text = element_text(size=text_size))+
theme(legend.title = element_text(size=text_size))
As some of the bar charts are so small and text doesn't fit, what I want to do is just have a (X%/Y%) above each bar that shows the percentage breakout. The values shown are in dollars.
Thank you!
This is some hack using data.table for aggregating the data and then displaying it with geom_text (there are probably better ways though)
library(data.table)
temp <- data.table(df1)[, per := (value/sum(value))*100, by = Name]
temp <- temp[, list(value = sum(value),
per = paste(sprintf("%.02f%%", per), collapse = " / "),
variable = variable), by = Name]
library(ggplot2)
text_size= 18
label_bottom_size=18
ggplot(df1, aes(x = Name, y = value, fill = variable)) +
geom_bar(stat = "identity")+
ggtitle(sprintf("Bar chart of Stuff" ))+
theme(axis.title=element_text(size=text_size),
plot.title=element_text(size=text_size+20),
axis.text.x= element_text(size=label_bottom_size),
axis.text.y= element_text(size=text_size),
legend.text = element_text(size=text_size),
legend.title = element_text(size=text_size)) +
geom_text(data = temp, aes(x = Name, y = value, label = per), vjust=-0.3)

Alignment of numbers on the individual bars

I have the need to place labels above bars on ggplot. I used to use the method found (HERE) but this does not appear to work anymore since my ggplot2 update as I now get the error message:
Error in continuous_scale(c("y", "ymin", "ymax", "yend", "yintercept", :
unused argument(s) (formatter = "percent")
How can I again plot numeric values above the bars when using the example:
df <- structure(list(A = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L,
3L), .Label = c("0-50,000", "50,001-250,000", "250,001-Over"), class = "factor"),
B = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), .Label = c("0-50,000",
"50,001-250,000", "250,001-Over"), class = "factor"), Freq = c(0.507713884992987,
0.258064516129032, 0.23422159887798, 0.168539325842697, 0.525280898876405,
0.306179775280899, 0.160958904109589, 0.243150684931507,
0.595890410958904)), .Names = c("A", "B", "Freq"), class = "data.frame", row.names = c(NA,
-9L))
library(ggplot2)
ggplot(data=df, aes(x=A, y=Freq))+
geom_bar(aes(fill=B), position = position_dodge()) +
geom_text(aes(label = paste(sprintf("%.1f", Freq*100), "%", sep=""),
y = Freq+0.015, x=A),
size = 3, position = position_dodge(width=0.9)) +
scale_y_continuous(formatter = "percent") +
theme_bw()
Running R 2.15 ggplot2 0.9 on a win 7 machine
The error is from the scale_y_continuous call. Formatting of labels is now handled by the labels argument. See the ggplot2 0.9.0 transition guide for more details.
There was another problem with the labels not lining up correctly; I fixed that by adding a group=B to the aesthetics for the geom_text; I'm not quite sure why this is necessary, though. I also took out x=A from the geom_text aesthetics because it was not needed (it would be inherited from the ggplot call.
library("ggplot2")
library("scales")
ggplot(data=df, aes(x=A, y=Freq))+
geom_bar(aes(fill=B), position = position_dodge()) +
geom_text(aes(label = paste(sprintf("%.1f", Freq*100), "%", sep=""),
y = Freq+0.015, group=B),
size = 3, position = position_dodge(width=0.9)) +
scale_y_continuous(labels = percent) +
theme_bw()

Resources