How to Separate Touching Labels in Stacked Bar charts ggplot2 - r

I have these stacked bar charts and the labels are touching, causing it to be difficult to differentiate. I would prefer if I was able to separate them a bit, as the information is important to present clearly!
Here is the plot:
Here is my code:
ggplot(data =GraphData, aes(x = factor(Year), y = value, fill = variable)) +
geom_bar(position = "fill", stat = 'identity') +
geom_col(position = position_stack(), color = "black")+
geom_text(data = GraphPercent, aes(y = GraphData$value, label = paste0(percent(value),"(", GraphData$value, ")")),
position = position_stack(vjust = 0.5), size = 3.5, col = c("black"))+
scale_fill_grey(start = 0.6, end = 1)+
theme(panel.background = element_blank(),axis.line = element_line(colour = "black"),)+
xlab("Year") +
ylab("Cases")
Thanks a lot I really appreciate it.

Related

R Getting 2 legends using ggplot2

I'm trying to create a more aesthetically pleasing graph. For some reason I am producing 2 legends at the top of my chart. I would like only the one on the right to remain, but I cannot figure out what I am doing wrong. Here is my code and graph.
plt <- ggplot(ac_total_melt, aes(Date, Value, fill = Action)) +
geom_line(
aes(color = Action),
size = .9
)+
geom_point(aes(colour = Action))+
ylab("")+
scale_color_manual(values=c('Dark Green','Dark red'), labels = c("Number Closed", "Number Opened"))+
geom_text_repel(
aes(color = Action, label = Value),
show.legend = FALSE,
family = "Lato",
fontface = "plain",
size = 4,
direction = "y"
) +
theme(legend.position="top")+
guides(color = guide_legend (override.aes = list(linetype = 0, size=5)))
plt
Data:
Looks like I needed to add show_guide = F to geom_point
The issue is that you re-labeled the fill scale, but not the color scale, so ggplot isn't able to merge them:
plt <- ggplot(ac_total_melt, aes(Date, Value, fill = Action, color = Action)) +
geom_line(size = .9) +
geom_point() +
ylab("") +
scale_color_manual(
values=c('blue', 'green'),
labels = c("Number Closed", "Number Opened"),
aesthetics = c("color", "fill") # apply this scale to both color and fill
) +
geom_text_repel(
aes(label = Value),
show.legend = FALSE,
family = "Lato",
fontface = "plain",
size = 4,
direction = "y"
) +
theme(legend.position = "top")+
guides(color = guide_legend(override.aes = list(linetype = 0, size = 5)))
plt

Positionning labels on a grouped bar chart with ggplot

I am having issues positionning my labels for my grouped bar chart.
Below a reproducible example, and on the image you can see where I would like the labels to be placed.
Not all on the same line, but each label aligned with each of the 3 bar chart, and ideally each label placed right above each corresponding bar chart.
Any idea how to achieve this? I want to keep a grouped bar chart and not a stacked bar chart.
data_F <- "https://raw.githubusercontent.com/max9nc9/Temp/main/temp.csv"
data_F <- read.csv(data_F, sep = ";")
colnames(data_F) <- c("Month_Year", "Type", "Amount")
data_F$Amount <- as.numeric(data_F$Amount)
Final_Graph <-
ggplot(data_F, aes(x = Month_Year, y = Amount, label = Amount, fill = Type)) +
geom_bar(position="dodge", stat = "identity") +
geom_text(size = 3, position = position_stack(vjust = 0.5), color = "black") +
theme(axis.text.x = element_text(angle = 90)) +
scale_fill_manual(values = c("#e62200", "#00c41d", "#f7b21e")) +
theme(plot.title = element_text(hjust = 0.5)) +
theme(plot.subtitle = element_text(hjust = 0.5))
Final_Graph
As you use position_dodge for the bars use it for the labels as well, where I use width = .9, which is the default for bars:
data_F <- "https://raw.githubusercontent.com/max9nc9/Temp/main/temp.csv"
data_F <- read.csv(data_F, sep = ";")
colnames(data_F) <- c("Month_Year", "Type", "Amount")
data_F$Amount <- as.numeric(data_F$Amount)
library(ggplot2)
ggplot(data_F, aes(x = Month_Year, y = Amount, label = Amount, fill = Type)) +
geom_bar(position="dodge", stat = "identity") +
geom_text(size = 3, position = position_dodge(width = .9), vjust = 0, color = "black") +
theme(axis.text.x = element_text(angle = 90)) +
scale_fill_manual(values = c("#e62200", "#00c41d", "#f7b21e")) +
theme(plot.title = element_text(hjust = 0.5)) +
theme(plot.subtitle = element_text(hjust = 0.5))

Overlapping text on top of geom_bar in ggplot2

I have made a barplot similar to the one below using ggplot2.
I cannot get the percentages on top of the bars to be centered and not overlapping of other bars and numbers. Sample code is below.
library(tidyverse)
cat1=c("cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1",
"cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2",
"cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3",
"cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4")
cat2=c("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12")
count1=round(rnorm(48,10))
fakeperc=rnorm(48,9)
df1=cbind(count1,fakeperc)
df2=cbind(cat1,cat2)
finaldf=as.data.frame(cbind(df1,df2))
finaldf$cat1=as.factor(finaldf$cat1)
finaldf$fakeperc=as.numeric(finaldf$fakeperc)
#finaldf$cat1=factor(finaldf$cat1,levels = c("cat1","cat2","cat3","cat4"))
finaldf$cat2 = factor(finaldf$cat2,
levels = c("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12"))
a=ggplot(data=finaldf,aes(x=cat1, y=count1,
fill=cat2,group=cat2)) +
geom_bar(stat='identity',color='black',width=.65,position=position_dodge(width=.9))+
scale_y_discrete(limits=0:50,breaks=c(0,10,20,30,40,50))+
scale_fill_brewer(palette="Set3") +
theme_classic() +
geom_text(data = finaldf,
aes(x=cat1,y=count1,group=cat2,
label=format(paste(round(fakeperc),"%",sep = ""))),inherit.aes = F,
color='black',position=position_dodge(.9),vjust=-.5,size=3)
a
When trying to add either nudge_y or nudge_x to the geom_text call, nothing happens. I suspect this is because there is already a position_dodge call. I am open any and all solutions to make these percentages non-overlapping and legible.
What do you think of this?
# I think you meant count1 to be numeric
finaldf$count1 <- as.numeric(finaldf$count1)
ggplot(data = finaldf,
aes(x = cat1,
y = count1,
fill = cat2,
group = cat2)) +
geom_col(color = 'black',
width = 0.65,
position = position_dodge(width = 0.9)) +
geom_text(data = finaldf,
aes(x = cat1,
y = count1,
group = cat2,
label = scales::percent(fakeperc/100, accuracy = 0.01)),
inherit.aes = FALSE,
color = 'black',
position = position_dodge(0.9),
hjust = -0.1,
size = 3) +
scale_y_continuous(limits = c(0,50), breaks = c(0,10,20,30,40,50)) +
scale_fill_brewer(palette = "Set3") +
theme_classic() +
coord_flip()
I cleaned up a bit the code (according to my taste)
I changed scale_y_numeric to scale_y_continuous (since count1 should be numeric)
I used coord_flip() to make it more readable
I used scales::percent to write percentage numbers
(don't know why you set up limits from 0 to 50 but I left them as I suppposed they were intended)
If you don't want to use coor_flip:
finaldf$count1 <- as.numeric(finaldf$count1)
ggplot(data = finaldf,
aes(x = cat1,
y = count1,
fill = cat2,
group = cat2)) +
geom_col(color = 'black',
width = 0.65,
position = position_dodge(width = 0.9)) +
geom_text(data = finaldf,
aes(x = cat1,
y = count1,
group = cat2,
label = scales::percent(fakeperc/100, accuracy = 0.01)),
inherit.aes = FALSE,
color = 'black',
position = position_dodge(0.9),
hjust = -0.1,
angle = 90,
size = 3) +
scale_y_continuous(limits = c(0,50), breaks = c(0,10,20,30,40,50)) +
scale_fill_brewer(palette = "Set3") +
theme_classic()
Is this what you are looking for:
library(ggplot2)
#Code
ggplot(data=finaldf,aes(x=cat2, y=count1,
fill=cat2,group=cat2)) +
geom_bar(stat='identity',color='black',
position=position_dodge(width=1))+
scale_fill_brewer(palette="Set3") +
theme_bw() +
geom_text(aes(x=cat2,y=count1,group=cat2,
label=format(paste(round(fakeperc),"%",sep = ""))),inherit.aes = F,
color='black',position=position_dodge(1),
size=3,vjust=-0.5)+
facet_wrap(.~cat1,scales = 'free_x',nrow = 1,strip.position = 'bottom')+
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
legend.position = 'top',
strip.background = element_blank(),
panel.spacing = unit(2, "lines"),
panel.grid = element_blank())+
guides(fill = guide_legend(nrow = 1))
Output:

How to align geom_text labels above dodged geom_col

I can't seem to find a way to get the text labels on this (dodged) geom_col to line up according to their respective columns.
I have tried numerous suggestions solutions on SO and other sites, and this is the closest I could get:
How do I fix this?
Code:
ggplot(leads[leads$key_as_string <= max(leads$key_as_string) - 1, ], aes(fill = type)) +
geom_col(aes(x = key_as_string, y = doc_count),
colour = "black",
position = position_dodge(1)) +
scale_y_continuous(limits = c(0, max(leads$doc_count))) +
geom_text(aes(x = key_as_string, y = doc_count, label = doc_count, group = key_as_string),
hjust = 0.5,
vjust = -0.5,
size = 3,
colour = "black",
position = position_dodge(1)) +
theme(panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
axis.text = element_text(colour = "black"))
As per my comment, group = key_as_string is the culprit here. The code is essentially telling ggplot to keep both labels with the same key_as_string value in the same group, negating the dodge command.
Illustration with the diamonds dataset below. We can see that removing the group aesthetic mapping changes the labels' positions:
p <- ggplot(diamonds %>%
filter(cut %in% c("Fair", "Good")) %>%
group_by(cut, clarity) %>%
summarise(carat = mean(carat)),
aes(clarity, carat, fill = cut, label = round(carat, 2))) +
geom_col(position = position_dodge(1))
gridExtra::grid.arrange(
p + geom_text(position = position_dodge(1), aes(group = clarity)),
p + geom_text(position = position_dodge(1)),
ncol = 1
)

ggplot2 remove one of two legends

I followed the general structure of the links below to plot two geom_boxplot's on top of each other, with the end goal of having the whiskers of one boxplot be dashed. I succeeded, but now there are two legends that I think correspond to each of the boxplots.
How to modify whiskers of a boxplot in ggplot2?
How to customize whisker lines on a geom_box plot differently than the lines of the box itself
t = ggplot(data = graph_data) +
geom_boxplot(aes(x = data_source, ymin = lwo, lower = pct_25, middle = median,
upper = pct_75, ymax = uwo, fill = data_source, linetype = data_source),
stat = 'identity', color = 'black') +
geom_boxplot(aes(x = data_source, ymin = pct_25, lower = pct_25, middle = median,
upper = pct_75, ymax = pct_75, fill = data_source),
stat = 'identity', color = 'black') +
geom_text(aes(x = data_source, y = -Inf, label = count_label),
vjust=-.5,stat='identity',size = 3,colour='Black',fontface='italic') +
theme_custom +
facet_grid(. ~ month, labeller = labeller(month = month_lbls)) +
theme(strip.background = element_rect(fill = NA)) +
theme(strip.text = element_text(size = rel(1.0), face = "bold")) +
scale_fill_manual(values = as.character(graph_colors), labels = names(graph_colors), guide = guide_legend(title = "Data Source")) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
theme(panel.margin = unit(3, "points")) +
theme(panel.grid.major.x = element_blank()) +
theme(panel.grid.minor.x = element_blank())
In the first geom_boxplot, the I specify the different line_type then overlay the interquartile range in the second geom_boxplot with a solid line. I think these two boxplot additions are creating the two legends, any ideas on how to remove the top legend (titled 'data_source')?

Resources