add labels to stacked bar chart with proportions using ggplot - r

I am trying to include labels to a stacked bar chart for proportions. I have been able to create the chart but I haven't been able to successfully add the labels. I've gotten labels but they are centered and overwriting one another....I know this has been asked, but I haven't found a solution that works.
The data is tidy in the sense that it is long
ggplot(data=dat) +
geom_bar(stat="identity",
mapping = aes(x=Vintage, y=OrigAmt, fill=fct_rev(Grade)),
position = "fill") +
ggtitle("Proportions by Grade") +
scale_fill_manual(values = c("grey", "gray40", "black")) +
guides(fill = guide_legend(reverse = TRUE, title="Grade")) +
scale_y_continuous(name="Proportion",label=percent_format()) +
theme_bw() +
theme(plot.title = element_text(hjust=0.5),
panel.border = element_blank(),
panel.grid = element_blank(),
axis.text.x = element_text(angle = 90))

Try adding this after geom_bar
geom_text(aes(y = cumsum(OrigAmt)-OrigAmt/2, label = Grade), show.legend = F)
Changing the y to a cumulative summation (cumsum) of the y variable minus half the y variable places the text in the middle of each section of each bar.
You can also add a color aesthetic and maybe turn Grade into a factor with defined color values

This appears to work.
ggplot(data = dat,
aes(y = freq, x = Vintage, fill = fct_rev(Grade))) +
geom_col() +
geom_text(aes(label = paste0(freq,"%")),
position = position_stack(vjust = 0.5), size = 2) +
scale_y_continuous(
labels = dollar_format(suffix = "%", prefix = "")) +
labs(title = "Distribution by Vintage",
subtitle = "xxx") +
labs(x = NULL, y = "Percentage") +
theme_bw() +
theme(legend.position = "bottom",
legend.direction = "horizontal",
legend.title = element_blank()) +
guides(fill = guide_legend(reverse = T)) +
scale_fill_manual(values = c("grey", "gray40", "brown")) +
theme(axis.text.x = element_text(angle = 90),
axis.text.x.bottom = element_text(vjust = 0.5))
However, I want to change the font colors and I can't see to be able to do that successfully.
For example, I want the label fonts to be BOLD and the font for A and B to be WHITE and the font for C to be BLACK. Thanks!

Related

Color dataset by group and add geom_vline to legend only

I have a genome-wide dataset that I'm trying to plot in the following way:
Have each chromosome be a separate color
Have specific windows highlighted by a bar (I'm using geom_vline) - this I'm getting from a
separate table
Have only geom_vline feature in the legend
I have tried many different things, but it seems I cannot have all three together!
Here is the link to both datasets:
allStats & allStats_fstPi_group15
With this code, I can have the first 2, but not the 3rd:
ggplot(allStats, aes(x = mid2, y = Fst_group1_group5,
color = as_factor(scaffold))) +
geom_point(size = 2) +
geom_vline(xintercept = chrom$add, color = "grey") +
scale_y_continuous(expand = c(0,0), limits = c(0, 1)) +
scale_x_continuous(labels = chrom$chrID, breaks = axis_set$center) +
scale_color_manual(values = rep(c("#276FBF", "#183059"), unique(length(chrom$chrID)))) +
scale_size_continuous(range = c(0.5,3)) +
labs(x = NULL,
y = "Fst SBM vs OC") +
theme_minimal() +
theme(
legend.position = "none",
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.title.y = element_text(),
axis.text.x = element_text()) +
geom_vline(data = allStats_fstPi_group15,
aes(xintercept = allStats_fstPi_group15$mid2),
color = "orange", show.legend = T)
With this one I can get 2 and 3 only (I'm not able to color code each block separately):
cols <- c("SBM vs OC" = rep(c("#276FBF", "#183059"), unique(length(chrom$chrID))),
"90th percentile (Fst vs Pi)" = "orange")
ggplot(allStats, aes(x = mid2)) +
geom_point(aes(y = Fst_group1_group5,
color = as_factor(scaffold)),
size = 2) +
geom_vline(data = allStats_fstPi_group15,
aes(xintercept = allStats_fstPi_group15$mid2,
color = "90th percentile (Fst vs Pi)")) +
scale_color_manual(values = cols)
I've seen the issue with the legend being that color needs to be within aes(), so my question is: is it impossible what I'm trying to do?

Changing the figure legend to indicate the line type... (ggplot2)

I have the formula below:
ggplot(Errortrialsmodifyoriginal, aes(x = Target, y = Absolutefirststoperror, color = as.character(Type), shape = as.character(Type))) +
geom_point(shape=16)+
geom_point(data=Errortrialoriginal,shape=19,size = 4,mapping=aes(x=Target, y=Absolutefirststoperror)) +
geom_line(data=Errortrialoriginal,aes(group=Type,linetype=Type),size=2,) +
scale_color_manual(name = "Condition", values = c("red","green","blue","red","green","blue")) +
scale_linetype_manual(name = "Condition",values = c("dashed","dashed","dashed","solid","solid","solid")) +
geom_errorbar(data=Errortrialoriginal,mapping=aes(x=Target, ymin=Absolutefirststoperror-SE,ymax=Absolutefirststoperror+SE),size=0.5) +
theme_bw() + guides(color = guide_legend("Condition"), shape = guide_legend("Condition"), linetype = guide_legend("Condition")) +
labs(x = "Target distance (vm)", y = "Absolute error in stop location (vm)") +
theme(axis.title.x = element_text(size=14, face="bold"), axis.title.y = element_text(size=14, face="bold"),legend.text=element_text(size=14),title=element_text(size=14,face="bold"), plot.title = element_text(hjust = 0.5), legend.title = element_text(size=14,face="bold"), axis.text.x=element_text(size=14),axis.text.y=element_text(size=14),panel.grid.major = element_blank(), panel.grid.minor = element_blank())
Which produces the graph:
How can I change my command to ensure that the dashed and solid lines are shown in the figure legend; because at the moment, the figure legend suggests that all the lines are solid, even though they are not?
I would be grateful for any advice!
To my opinion, the legend is correctly displayed but you can't see it because you have big points front of the linetype. You should increase the legend box to see it.
Here an example with this dummy example:
library(ggplot2)
ggplot(my_data, aes(x = dose, y = length, color = supp, linetype = supp))+
geom_line()+
geom_point(size = 4)
library(ggplot2)
ggplot(my_data, aes(x = dose, y = length, color = supp, linetype = supp))+
geom_line()+
geom_point(size = 4)+
theme(legend.key.size = unit(3,"line"))
So, with your code, you can do something like that:
library(ggplot2)
ggplot(Errortrialsmodifyoriginal,
aes(x = Target,
y = Absolutefirststoperror,
color = Type)) +
geom_point()+
geom_line(data=Errortrialoriginal,
aes(group=Type,
linetype=Type)) +
scale_color_manual(name = "Condition", values = rep(c("red","green","blue"),2)) +
scale_linetype_manual(name = "Condition",values = rep(c("dashed","solid"),each =3)) +
geom_errorbar(data=Errortrialoriginal,
mapping=aes(x=Target,
ymin=Absolutefirststoperror-SE,
ymax=Absolutefirststoperror+SE),size=0.5) +
theme_bw() +
guides(color = guide_legend("Condition"), shape = guide_legend("Condition"), linetype = guide_legend("Condition")) +
labs(x = "Target distance (vm)", y = "Absolute error in stop location (vm)") +
theme(axis.title.x = element_text(size=14, face="bold"),
axis.title.y = element_text(size=14, face="bold"),
legend.text=element_text(size=14),
title=element_text(size=14,face="bold"),
plot.title = element_text(hjust = 0.5),
legend.title = element_text(size=14,face="bold"),
axis.text.x=element_text(size=14),
axis.text.y=element_text(size=14),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.key.size = unit(3,"line"))
Does it answer your question ?
If not, please consider providing a reproducible example of your dataset (see: How to make a great R reproducible example)

Trouble with overlapping labels (geom_text)

Trouble with overlapping geom_text labels on pie chart
library(scales)
blank_theme <- theme_minimal()+
theme(
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.border = element_blank(),
panel.grid=element_blank(),
axis.ticks = element_blank(),
plot.title=element_text(size=14, face="bold")
)
df6 <- data.frame(group = c("Seedling","Ground", "Fern", "Moss"),value = c(2.125,80.125, 11.376,6.375))
# Create a basic bar
pie6 = ggplot(df6, aes(x="", y=value, fill=group)) + geom_bar(stat="identity", width=1) + blank_theme + theme(axis.text.x=element_blank())
# Convert to pie (polar coordinates) and add labels
pie6 = pie6 + coord_polar("y", start=0) + geom_text(aes( label = paste0((value), "%")),position = position_stack(vjust = 0.5))
# Remove labels and add title
pie6 = pie6 + labs(x = NULL, y = NULL, fill = NULL, title = "Understory Composition, Site 2")
# Tidy up the theme
pie6 = pie6 + theme_classic() + theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, color = "black"))
pie6
This is my current output. How can i change the labels such that they do not overlap? i have tried various hjust and vjust, positions and position_stack but to no avail
Any help appreciated. thank you.
A manual approach to this problem could be to manipulate the orientation of the text by setting the angle parameter in the geom_text function. This allows you to set the orientation of all text fragments at once by assigning a singel value to angle. You may also set the angle for the individual text items as illustrated below.
ggplot(df6, aes(x = "", y = value, fill = group)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y", start = 0) +
blank_theme +
theme(axis.text.x = element_blank()) +
geom_text(aes(label = paste0((value), "%")),
position = position_stack(vjust = 0.5),
angle = c(-90, -90, 0, -90)) ####### here
The code below adjust the angle depending on the pie it describes.
ggplot(df6, aes(x = "", y = value, fill = group)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y", start = 0) +
blank_theme +
theme(axis.text.x = element_blank()) +
geom_text(aes(label = paste0((value), "%")),
position = position_stack(vjust = 0.5),
angle = c(-97, -110, 0, -70)) ####### here
Another way to work around the problem you state, is to play with the start parameter of the coord_polar function:
ggplot(df6, aes(x = "", y = value, fill = group)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y", start = 180) + ####### here
blank_theme +
theme(axis.text.x = element_blank()) +
geom_text(aes(label = paste0((value), "%")) ,
position = position_stack(vjust = 0.5))
Have you tried using the package ggrepel? If so I recommend. It automatically stops labels overlapping and finds a fit for each other them.
#Install ggrepel package
install.packages("ggrepel", dependencies=TRUE)
df6 <- data.frame(group = c("Seedling","Ground", "Fern", "Moss"),value = c(2.125,80.125, 11.376,6.375))
# Create a basic bar
pie6 = ggplot(df6, aes(x="", y=value, fill=group)) + geom_bar(stat="identity",
width=1) + blank_theme + theme(axis.text.x=element_blank())
# Convert to pie (polar coordinates) and add labels using ggrepel
pie6 = pie6 + coord_polar("y", start=0) + ggrepel::geom_text_repel(aes( label =
paste0((value), "%")),position = position_stack(vjust = 0.5))
# Remove labels and add title
pie6 = pie6 + labs(x = NULL, y = NULL, fill = NULL, title = "Understory Composition, Site 2")
# Tidy up the theme
pie6 = pie6 + theme_classic() + theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, color = "black"))
pie6

Labelling and theme of ggalluvial plot in R

For the past hours I have tried to understand the whole design/theme/labelling concept around ggalluvial, but I failed.
Within minutes I was able to produce the kind of graph I want (thanks to the package ggalluvial), but I can't figure how to produce the correct labelling/theme I'd like to have.
This is where I am currently:
This is where I was initially:
To get you to understand where I am, here's a reproducible example
I used the following code:
library(ggalluvial)
ds <- as.data.frame(Titanic)
ggplot(ds,
aes(weight = Freq, axis1 = Sex, axis2 = Class)) +
geom_alluvium(aes(fill = Sex), width = 1/12) +
geom_stratum(width = 1/4, fill = "black", color = "grey") +
scale_x_continuous(breaks = 1:2, labels = c("Sex", "Class")) +
scale_fill_manual(name = "", values=c("#A0A0A0", "#494949")) +
ggtitle("Titanic Survival") +
theme_bw() +
geom_text(stat = "stratum", color="white",label.strata = TRUE,
angle=c(90,90,0,0,0,0) , size=6,
nudge_y=c(1,2,3,4,5,0)) +
theme(legend.position = "bottom",
title = element_text(size = 20),
legend.text = element_text(size = 20),
axis.text.y = element_blank(),
axis.text.x = element_text(size=20))
What I would like to change:
turn labels on the left vertically
done
make labels on the right not overlap (not visible with the Titanic data)
I tried nudging. But it may be more useful to place these legends outside the graph, maybe like on an axis?
remove y-axis labels
done
Understand with what command I can change each of the text elements size (title, legend, labels, axis labels)
dome
I am very happy for any help on this. Thank you.
You can try:
ggplot(ds,
aes(weight = Freq, axis1 = Sex, axis2 = Class)) +
geom_alluvium(aes(fill = Sex), width = 1/12) +
geom_stratum(width = 1/16, fill = "black", color = "grey") +
scale_x_continuous(breaks = 1:2, labels = c("Sex", "Class")) +
scale_fill_manual(name = "", values=c("#A0A0A0", "#494949")) +
ggtitle("Titanic Survival") +
theme_bw() +
geom_text(stat = "stratum", color="red",label.strata = TRUE, angle=c(0,0,45,45,45,45),size=5) +
theme(legend.position = "bottom",
title = element_text(size = 20),
legend.text = element_text(size = 20),
axis.text.y = element_blank(),
axis.text.x = element_text(size=20))
add a vector with the same length of labels like angle=c(0,0,45,45,45,45)
add axis.text.y = element_blank() in theme()
pending
Sizes via theme
via theme() such as x-axis labels
text in plot via size=5 in geom_text()

ggplot pie chart choose axes ticks

I would like to know if it's possible to modify the ticks of x axis with a ggplot pie chart.
Here what I can do :
# Some colors
couleurs <- data.frame(
id=seq(1,17,1),
mix=c(c(rep(1,6),rep(2,7),rep(3,4))),
html=c("#A00020","#109618","#388EE4","#C484D1","#FFAA33","#CCCDD0","#004AC5","#F80094","#CB5023","#638995","#33CFCF","#95DC4E","#F7D633","#5C403C","#F72020","#00D96C","#FDE4C5")
)
couleurs$html <- factor(couleurs$html, levels = couleurs$html[order(couleurs$id, decreasing = FALSE)])
# Data
activite <- data.frame(label=c("B to B","B to C","B to B / B to C", "B to B"), cible=c(rep("Externe",3), "Interne"), nb=c(12,9,3,12))
activite$label <- factor(activite$label, levels = activite$label[order(activite$nb[activite$cible=="Externe"], decreasing = TRUE)])
library(plyr)
activite<-ddply(activite,.(cible),transform,pc=(nb/sum(nb))*100)
activite
# Pie chart
library(ggplot2)
ggplot(data = activite, aes(x = "", y = nb, fill = label )) +
geom_bar(stat = "identity", position = position_fill(), width = 1) +
coord_polar(theta= "y", start = 0, direction = -1) +
labs(fill="") +
scale_fill_manual(values=as.character(couleurs$html[1:nrow(activite)]), labels=paste(activite$label,"\t\t\t",sep="")) +
geom_text(aes(label = paste(pc,"%", sep=" ")), size=4, colour = "white", fontface = "bold", position = position_fill(vjust = 0.5)) +
theme(strip.text = element_text(size=20, face = "bold", ), strip.background = element_rect(fill="grey75")) +
theme(panel.background = element_rect(fill = "white")) +
theme(plot.background = element_rect(fill = "grey92")) +
theme(legend.position="bottom", legend.background = element_rect(fill="grey92")) +
theme(legend.key = element_blank()) +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_line(colour = "grey75")) +
theme(axis.text.y = element_blank()) +
theme(axis.ticks.length = unit(0, "mm")) +
theme(axis.title.x = element_blank(),axis.title.y = element_blank()) +
theme(legend.box.spacing = unit(1, "mm")) +
facet_wrap(~ cible)
Here my result:
After several hours of serach, I didn't find a solution to create what I want. The exact same pie chart but with personalised ticks like that :
With these particular conditions :
- do not change the direction of the data in the pie chart, I want it like exactly this
- if possible (but if not possible, it's okay), I would like the ticks' labels not superposed with the axis.
If someone can help me, I would really appreciate.
Here's one solution:
ggplot(data = activite %>%
group_by(cible) %>%
arrange(desc(nb)) %>%
mutate(axis.label = cumsum(nb),
axis.position = cumsum(pc)/100) %>%
mutate(axis.label = ifelse(pc == min(pc),
paste(axis.label, "0", sep = "-"),
axis.label)),
aes(x = 1, y = nb, fill = label )) +
geom_segment(aes(x = 1, xend = 1.6, y = axis.position, yend = axis.position),
colour = "grey75") +
geom_vline(xintercept = 1.6, colour = "grey75") +
geom_bar(stat = "identity", position = position_fill(reverse = T), width = 1) +
coord_polar(theta= "y", start = 0, direction = 1) +
labs(fill="") +
scale_fill_manual(values=as.character(couleurs$html[1:nrow(activite)]), labels=paste(activite$label,"\t\t\t",sep="")) +
geom_text(aes(label = paste(pc,"%", sep=" ")), size=4, colour = "white",
fontface = "bold", position = position_fill(vjust = 0.5, reverse = T)) +
geom_text(aes(x = 1.7, label = axis.label), size = 3,
position = position_fill(reverse = T)) +
theme(strip.text = element_text(size=20, face = "bold", ), strip.background = element_rect(fill="grey75")) +
theme(panel.background = element_rect(fill = "white")) +
theme(plot.background = element_rect(fill = "grey92")) +
theme(legend.position="bottom", legend.background = element_rect(fill="grey92")) +
theme(legend.key = element_blank()) +
theme(panel.grid = element_blank()) +
theme(axis.text = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.title = element_blank()) +
theme(legend.box.spacing = unit(1, "mm")) +
facet_wrap(~ cible)
Explanation:
The sequence in your labels went clockwise, while the direction of the polar coordinates went counter-clockwise. That makes labelling rather troublesome. I switched the direction for polar coordinates, & added reverse = T inside the position adjustment calls for the geoms.
It's hard to assign different axis breaks to different facets of the same plot, so I didn't. Instead, I modified the data to include calculated axis labels / margin positions, added margins via geom_segment / geom_vline, & hid the axis text / ticks in theme().

Resources