How to adjust one of the bar's label in histogram? - r

My codes is here
Yr = c("2016","2017","2016","2017","2016","2017")
Type = c("A","A","B","B","C","C")
Value = c(73,183,160,476,11,73)
Percentage = c(29.92,25.00,65.57,65.03,4.51,9.97)
p1Data <- data.frame(Yr,Type,Value,Percentage)
library(ggplot2)
p1 <- ggplot(p1Data, aes(Type, Value, fill = Yr)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
theme(axis.title.x = element_blank(), plot.title = element_text(hjust = 0)) +
geom_text(aes(label = paste(Value, paste(Percentage, "%"), sep = "\n"), y = Value), size = 4, vjust = 1.5, position = position_dodge(width = 0.9)) +
ggtitle("2016 V.S. 2017") +
labs(fill = "Catagory")

You could change vjust = 1.5 to vjust = "inwards" in your geom_text.
ggplot(p1Data, aes(Type, Value, fill = Yr)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
theme(axis.title.x = element_blank(), plot.title = element_text(hjust = 0)) +
geom_text(aes(label = paste(Value, paste(Percentage, "%"), sep = "\n"),
y = Value),
size = 4,
vjust = "inward",
position = position_dodge(width = 0.9)) +
ggtitle("2016 V.S. 2017") +
labs(fill = "Catagory")

Related

geom_bar + coord_polar labels with lines

I am trying to label the series of concentric circles below with the labels from C in the data frame
I am aware that I could use something like geom_text_repel but I cannot seem to get it to work.
In addition, I cannot seem to get rid of the tick marks on the upper left.
df <- data.frame(C=c(rep("The macro-environment",4),rep("The industry",4),rep("Competitors",4),rep("The organisation",4)))
ggplot(df, aes(factor(1), fill = C)) +
geom_bar(width = 1, colour = NA, show.legend = FALSE, alpha = .8) +
coord_polar() +
labs(
x = "",
y = ""
) +
scale_fill_manual(values = c("#289045", "#beddc7", "#d4dfe9", "#286291")) +
theme(axis.ticks.x = element_blank(),
axis.ticks.y = element_blank()) +
theme_minimal()
A second option would be to add your labels as curved labels using the geomtextpath package:
library(ggplot2)
library(geomtextpath)
ggplot(df, aes(factor(1), fill = C)) +
geom_bar(width = 1, colour = NA, show.legend = FALSE, alpha = .8) +
geom_textpath(aes(x = .5, label = C, group = C),
stat = "count", position = position_stack(vjust = .5),
vjust = 1
) +
coord_polar() +
labs(
x = "",
y = ""
) +
scale_fill_manual(values = c("#289045", "#beddc7", "#d4dfe9", "#286291")) +
theme_void()
You could do:
ggplot(df, aes(factor(1), fill = C)) +
geom_bar(width = 1, colour = NA, show.legend = FALSE, alpha = .8) +
geom_text(stat = 'count', aes(label = C), size = 6,
position = position_stack(vjust = 0.5),
vjust = c(0.5, 0.5, 0.5, 2)) +
coord_polar(start = pi) +
labs(x = NULL, y = NULL ) +
scale_fill_manual(values = c("#289045", "#beddc7", "#d4dfe9", "#286291")) +
theme_void()

Add totals on top of each bar

I am plotting my data and want to display totals on top of each bar but as soon as I add total count the bars disappear.
long<- data.frame(
Name = c("abc","abc","abc","gif","gif","gif","xyz","xyz","xyz"),
variable = c("a","b","c","a","b","c","c","b","a"),
value = c(4,6,NA,2,8,1,6,NA,NA))
Code
p<-long %>%
ggplot() + aes(Name, value, fill=variable) +
geom_bar(stat="summary", position = "fill") +
scale_y_continuous(labels = scales::percent_format()) +
ylab("Total_num") +
ggtitle("Totalnum") +
theme(plot.title = element_text(size = 20, hjust = 0.5)) +
theme(axis.text.x = element_text(angle = 75, vjust = 0.95, hjust=1))
p+ stat_summary(fun.y = sum, aes(label = ..y.., group = Name)+
geom_text(stat='value', aes(group=Name, label=.."value"..), position = position_stack(vjust = 0.5))
You can achieve that creating another df with the sum of value per Name and passing this to geom_text()
long<- data.frame(
Name = c("abc","abc","abc","gif","gif","gif","xyz","xyz","xyz"),
variable = c("a","b","c","a","b","c","c","b","a"),
value = c(4,6,NA,2,8,1,6,NA,NA))
long_totals <- long %>%
group_by(Name) %>%
summarise(Total = sum(value, na.rm = T))
p <- ggplot()+
geom_bar(data = long,
aes(x = Name,
y = value,
fill=variable),
stat="summary",
position = "fill") +
geom_text(data = long_totals,
aes(y = 100,
x = Name,
label = Total),
size = 7,
position = position_fill(vjust = 1.02)) +
scale_y_continuous(labels = scales::percent_format()) +
ylab("Total_num") +
ggtitle("Totalnum") +
theme(plot.title = element_text(size = 20, hjust = 0.5)) +
theme(axis.text.x = element_text(angle = 75, vjust = 0.95, hjust=1))

How do I neatly align my stacked barchart labels, with differing alignments to each side of the bar?

I have my labels roughly aligned to each side of my stacked bar chart. The problem is that they look like a mess because they aren't right and left justified on either side of the bar. How do I fix this so that they look professional?
df3 <- data.frame(
Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
)
# Sort order
level_order <- df3 %>%
arrange(desc(Amount))
ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) +
geom_bar(position="stack", stat="identity", width = 0.55) +
scale_fill_brewer(palette = "Blues", direction = -1) +
theme_void() +
geom_text(aes(label = paste0("$", Amount)),
position = position_stack(vjust = 0.5),
hjust = -3.1,
size = 5) +
geom_text(aes(label = Label),
position = position_stack(vjust = 0.5),
hjust = 5,
size = 5) +
theme(legend.position = "none") +
theme(plot.title = element_text(size = 50, hjust = .5, vjust = 0)) +
ggtitle("Food Costs by Reindeer")
hjust determines the text alignment (with 0 being left-aligned, and 1 right-aligned). The x co-ordinate of your geom_text at the moment is defaulted to 1, so changing this will change the position of the text.
ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) +
geom_bar(position="stack", stat="identity", width = 0.55) +
scale_fill_brewer(palette = "Blues", direction = -1) +
theme_void() +
geom_text(aes(x=0.6, label = paste0("$", Amount)),
position = position_stack(vjust = 0.5),
hjust = 0.5,
size = 5) +
geom_text(aes(x=1.4, label = Label),
position = position_stack(vjust = 0.5),
hjust = 0.5,
size = 5) +
theme(legend.position = "none") +
theme(plot.title = element_text(size = 50, hjust = .5, vjust = 0)) +
ggtitle("Food Costs by Reindeer")
You can also pass hjust as an aesthetic. In order to do that, you will need to prepare the labelling as a separate data frame. Then, you only need to call geom_text once. I don't say this is necessarily better, but just pointing out that this is possible. A few more comments in the code, also regarding a few common pitfalls.
library(tidyverse)
df3 <- data.frame(
Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
) %>%
## arrange step here
arrange(desc(Amount))
## I like to prepare the data outside ggplot
label_df <- df3 %>%
mutate(Amount_lab = paste0("$", Amount)) %>%
pivot_longer(-Amount) %>%
## this adds a column for your adjustment, and the x position compared with the central column
mutate(hjust = rep(0:1, nrow(.)/2),
x = rep(c(1.21, .79), nrow(.)/2))
ggplot(mapping = aes(y = Amount)) +
## geom_col is geom_bar(stat = "identity"), stack is default, so you can omit it
## call data in the geom layers
## set x to 1
## width = .4 so it matches your selected x from above
geom_col(data = df3, aes(x = 1, fill=fct_inorder(Label)), width = .4) +
scale_fill_brewer(palette = "Blues", direction = -1) +
## need to reverse both y and value, weirdly
geom_text(data = label_df, aes(x, y = rev(Amount), label = rev(value),
## this is the main trick
hjust = hjust),
position = position_stack(vjust = 0.5) ) +
## sadly, need to turn clip off
coord_cartesian(clip = "off") +
theme_void() +
## call theme only once!!
theme(legend.position = "none",
plot.title = element_text(size = 20, hjust = .5, vjust = 0),
## you need to add a margin
plot.margin = margin(r = .6, l = .6, unit = "in")) +
ggtitle("Food Costs by Reindeer")
Created on 2021-12-20 by the reprex package (v2.0.1)
Try fixing the x co-ordinate in the call to geom_text and managing alignment with hjust...
df3 <- data.frame(
Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
)
library(ggplot2)
library(dplyr)
library(forcats)
level_order <- df3 %>%
arrange(desc(Amount))
ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) +
geom_bar(position="stack", stat="identity", width = 0.55) +
scale_fill_brewer(palette = "Blues", direction = -1) +
theme_void() +
geom_text(aes(x = 1.3, label = paste0("$", Amount)),
position = position_stack(vjust = 0.5),
hjust = 0,
size = 5) +
geom_text(aes(x = 0.6, label = Label),
position = position_stack(vjust = 0.5),
hjust = 0,
size = 5) +
theme(legend.position = "none") +
theme(plot.title = element_text(size = 50, hjust = .5, vjust = 0)) +
ggtitle("Food Costs by Reindeer")
Created on 2021-12-19 by the reprex package (v2.0.1)
Using Peter's answer above (reminding me of the "x" position argument I forgot existed), this was the final fix that got what I was looking for. hjust = 0 is left-justification and hjust = 1 is right justification.
library(tidyverse)
library(grid)
df3 <- data.frame(
Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
)
# Sort order
level_order <- df3 %>%
arrange(desc(Amount))
ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) +
geom_bar(position="stack", stat="identity", width = 0.55) +
scale_fill_brewer(palette = "Blues", direction = -1) +
theme_void() +
geom_text(aes(x = 1.3, label = paste0("$", Amount)),
position = position_stack(vjust = 0.5),
hjust = 0,
size = 5) +
geom_text(aes(x = 0.7, label = Label),
position = position_stack(vjust = 0.5),
hjust = 1,
size = 5) +
theme(legend.position = "none",
plot.margin = unit(c(0,0,2,0), "cm"))
grid.text("Food Costs by Reindeer", x = unit(0.5, "npc"), y = unit(0, "npc"),
vjust = -0.5, gp = gpar(cex=4))

R geom_col label cutoff either above or below

Does anyone have a solution to this graph? The labels above the bar graph are cutoff either at the top or at the bottom, depending on how I do the vertical adjustment. I don't think I can reduce the size of the font enough to fit and be readable.
On the one hand, I have this, where the label is cut off in the first bar for Paid Search
ggplot(all_rb6, aes(x = `Number of Touchpoints`, y = Percent, fill = Campaign)) +
geom_col(position = 'dodge') +
facet_wrap(~Campaign) +
labs(title="Title", subtitle = "subtitle") +
theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
theme(plot.subtitle = element_text(hjust = 0.5)) +
labs(caption = "Marketing") +
geom_text(aes(label = paste(format(Percent), "%")), vjust = -0.5, position = position_dodge(.9), colour = "black") +
scale_fill_brewer(palette = "Pastel1")
On the other hand, I have this graph, where the labels are cut off for the third bar in all of them.
ggplot(all_rb6, aes(x = `Number of Touchpoints`, y = Percent, fill = Campaign)) +
geom_col(position = 'dodge') +
facet_wrap(~Campaign) +
labs(title="Title", subtitle = "subtitle") +
theme(plot.title = element_text(hjust = 0.5, face = "bold")) +
theme(plot.subtitle = element_text(hjust = 0.5)) +
labs(caption = "Marketing") +
geom_text(aes(label = paste(format(Percent), "%")), vjust = 1.5, position = position_dodge(.9), colour = "black") +
scale_fill_brewer(palette = "Pastel1")

Automatically select a more distinctive color pallet for ggplot2

I use the following code to generate a series of plots which include both geom_boxplot and geom_point. I want the points to have more distinctive colors without me defining what they are every time:
for (i in 1:length(Girder.Plot)) {
Plot.Girder <- ggplot(data = subset(Girder.Plot[[i]], Names == "Sample"),
aes(x = Type, y = Moment, fill = factor(Spacing,levels = c("9","12","15")))) +
geom_boxplot(outlier.shape = NA, position = position_dodge(width = 0.75)) +
stat_summary(fun = mean, geom="point", shape=23, size=2,
position = position_dodge(width = 0.75)) +
stat_boxplot(geom='errorbar', linetype=1, width=0.5,
position = position_dodge(width = 0.75)) +
geom_point(data = subset(Girder.Plot[[i]], Names == "No Factor"),
aes(colour = Names), position = position_dodge(width = 0.75)) +
geom_point(data = subset(Girder.Plot[[i]], Names == "Factor 1"),
aes(colour = Names), position = position_dodge(width = 0.75)) +
geom_point(data = subset(Girder.Plot[[i]], Names == "Factor 2"),
aes(colour = Names), position = position_dodge(width = 0.75)) +
geom_point(data = subset(Girder.Plot[[i]], Names == "Factor 3"),
aes(colour = Names), position = position_dodge(width = 0.75)) +
labs(x = element_blank(), y = element_blank(),
title = paste0("Moment Live Load Distribution Factors \n Along the Roadway Width for \n Ultra-Girder Section: UG-"
,str_extract(names(Girder.Plot)[i],"\\d+")),
fill = "Girder Spacing (ft):", colour = element_blank()) +
theme_classic() + ylim(0.4, 1.1) +
theme(plot.title = element_text(hjust = 0.5, margin = margin(45,0,20,0),
face = "bold", size = 18),
legend.title.align = 0.5, legend.position = "bottom",
legend.box.background = element_rect(colour = "black", size = 0.5),
legend.box.margin = margin(0,0,0,0))
print(Plot.Girder)
}
Use scale_fill_brewer/scale_color_brewer.
library(ggplot2)
ggplot(iris, aes(Species, Sepal.Length, fill = Species)) +
geom_boxplot() +
theme_minimal() +
scale_fill_brewer(palette = "Set1")
To see available palettes.
RColorBrewer::display.brewer.all()

Resources