How to add text on the top of bar chart in ggplot R?
Column label
was added for labeling on the plot.
BTW, the label of your desired outcome is switched. (According to your df
, 89, 46.4 for Canada).
require(ggplot2)
require(dplyr)
df <- data.frame (Origin = c("Canada", "Canada","USA","USA"),
Year = c("2021", "2022","2021","2022"),
Sales = c(103, 192, 144, 210),
diff = c(89, " ",66," "),
perdiff = c(86.4, " ",45.83," "))
df <- df %>% mutate(label= ifelse(diff!=" ",paste0(diff,", ",perdiff,'%'),NA))
ggplot(df, aes(fill=Year, y=Origin, x=Sales)) +
geom_bar(position="dodge", stat="identity")+
geom_text(aes(label=label, x=200), fontface='bold') +
scale_x_continuous(breaks=seq(0,200,25))+
theme()
#> Warning: Removed 2 rows containing missing values (geom_text).
Created on 2022-05-03 by the reprex package (v2.0.1)
Staggering labels or adding only selected labels on ggplot stacked bar chart
If I were you, I'll only display labels for Pct
greater than 5% using if_else()
in geom_text(aes())
. If it's less than 5%, display nothing.
Also, since your geom_bar
position is fill
, you should also use position = position_fill()
in geom_text
to align the position.
library(tidyverse)
data %>%
select(q1a:q1b) %>%
pivot_longer(cols = everything(), names_to = "Question") %>%
filter(!is.na(value)) %>%
dplyr::count(Question, value) %>%
group_by(Question) %>%
mutate(Pct = n / sum(n)) %>%
ggplot(aes(fill = value, x = Pct, y = fct_rev(Question))) +
geom_bar(position = "fill", stat = "identity") +
geom_text(aes(label = if_else(Pct > 0.05, paste0(sprintf("%1.0f", Pct * 100), "%"), NULL)),
position = position_fill(vjust = 0.5), size = 3) +
scale_fill_brewer(palette = "Blues") +
theme_bw() +
scale_x_continuous(labels = scales::percent) +
labs(title = "Question 1", y = "Question", x = "Percentage") +
theme(legend.title = element_blank())
Include bar labels inside ggplot plot bar chart
An option would be using geom_text
and displaying the labels inside your bars. You can use the following code:
library(tidyverse)
df %>% mutate(name = fct_reorder(name,total)) %>% ggplot(aes(pos, total,fill = pos, group = total,label = name)) +
geom_col(show.legend = FALSE,
position = position_dodge2(),width = .5) +
geom_text(aes(group = name),color = "white",
position = position_dodge2(width = 0.5),
show.legend = FALSE, hjust = 1.2, size = 2) + coord_flip()
Output:
Adding labels to ggplot bar chart
Here you go:
library(scales)
ggplot(x, aes(x = filename, fill = variable)) +
geom_bar(stat="identity", ymin=0, aes(y=value, ymax=value), position="dodge") +
geom_text(aes(x=filename, y=value, ymax=value, label=value,
hjust=ifelse(sign(value)>0, 1, 0)),
position = position_dodge(width=1)) +
scale_y_continuous(labels = percent_format()) +
coord_flip()
Can I add grouping line labels above my ggplot bar/column chart?
One approach to achieve your desired result would be via geom_segment
. To this end I first prepare a dataset containing the start and end positions of the segments to be put on top of the bars by rating group. Basically this involves converting the discrete locations to numerics.
Afterwards it's pretty straightforward to add the segments and the labels.
library(tidyverse)
library(hrbrthemes)
library(scales)
# Loading a colorblind accessible palette
cbbPalette <- c("#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
width <- .45 # Half of default width of bars
df_segment <- contin_cases %>%
ungroup() %>%
# Convert location to numerics
mutate(loc_num = as.numeric(fct_reorder(location, prop_total))) %>%
group_by(rating) %>%
summarise(x = min(loc_num) - width, xend = max(loc_num) + width,
y = max(prop_total) * 1.5, yend = max(prop_total) * 1.5)
ggplot(
contin_cases,
aes(
x = reorder(location, prop_total),
y = prop_total,
fill = location
)
) +
geom_bar(stat = "identity", color = "white") +
ylim(0, 1) +
geom_segment(data = df_segment, aes(x = x, xend = xend, y = max(y), yend = max(yend),
color = rating, group = rating),
inherit.aes = FALSE, show.legend = FALSE) +
geom_text(data = df_segment, aes(x = .5 * (x + xend), y = max(y), label = str_to_title(rating), color = rating),
vjust = -.5, inherit.aes = FALSE, show.legend = FALSE) +
geom_text(aes(
y = prop_total,
label = round(prop_total, 4)
),
vjust = -1.5
) +
scale_fill_manual(
name = "Continent",
values = cbbPalette
) +
labs(
title = "Proportion of total COVID-19 Cases Per Continent",
caption = "Figure 1. Asia leads total COVID case count as of May 23rd, 2021. No data exists in this dataset for Antarctica."
) +
ylab("Proportion of total cases") +
xlab("") + # this makes x-axis blank
theme_classic() +
theme(
plot.caption = element_text(hjust = 0, face = "italic")
)
DATA
contin_cases <- structure(list(location = c(
"Africa", "Asia", "Australia", "Europe",
"North America", "South America"
), total_cases = c(
4756650, 49204489,
30019, 46811325, 38790782, 27740153
), prop_total = c(
0.0284197291646085,
0.293983843894959, 0.000179355607369132, 0.2796853202015, 0.231764691226676,
0.165740097599109
), rating = c(
"low", "high", "low", "high",
"high", "medium"
)), class = c(
"grouped_df", "tbl_df", "tbl",
"data.frame"
), row.names = c(NA, -6L), groups = structure(list(
location = c(
"Africa", "Asia", "Australia", "Europe", "North America",
"South America"
), .rows = structure(list(
1L, 2L, 3L, 4L,
5L, 6L
), ptype = integer(0), class = c(
"vctrs_list_of",
"vctrs_vctr", "list"
))
), row.names = c(NA, -6L), class = c(
"tbl_df",
"tbl", "data.frame"
), .drop = TRUE))
Adding labels to percentage stacked barplot ggplot2
To put the percentages in the middle of the bars, use position_fill(vjust = 0.5)
and compute the proportions in the geom_text
. These proportions are proportions on the total values, not by bar.
library(ggplot2)
colors <- c("#00405b", "#008dca", "#c0beb8", "#d70000", "#7d0000")
colors <- setNames(colors, levels(newDoto$Q29_1String))
ggplot(newDoto, aes(pid3lean, fill = Q29_1String)) +
geom_bar(position = position_fill()) +
geom_text(aes(label = paste0(..count../sum(..count..)*100, "%")),
stat = "count",
colour = "white",
position = position_fill(vjust = 0.5)) +
scale_fill_manual(values = colors) +
coord_flip()
Package scales
has functions to format the percentages automatically.
ggplot(newDoto, aes(pid3lean, fill = Q29_1String)) +
geom_bar(position = position_fill()) +
geom_text(aes(label = scales::percent(..count../sum(..count..))),
stat = "count",
colour = "white",
position = position_fill(vjust = 0.5)) +
scale_fill_manual(values = colors) +
coord_flip()
Edit
Following the comment asking for proportions by bar, below is a solution computing the proportions with base R only first.
tbl <- xtabs(~ pid3lean + Q29_1String, newDoto)
proptbl <- proportions(tbl, margin = "pid3lean")
proptbl <- as.data.frame(proptbl)
proptbl <- proptbl[proptbl$Freq != 0, ]
ggplot(proptbl, aes(pid3lean, Freq, fill = Q29_1String)) +
geom_col(position = position_fill()) +
geom_text(aes(label = scales::percent(Freq)),
colour = "white",
position = position_fill(vjust = 0.5)) +
scale_fill_manual(values = colors) +
coord_flip() +
guides(fill = guide_legend(title = "29")) +
theme_question_70539767()
Theme to be added to plots
This theme
is a copy of the theme defined in TarJae's answer, with minor changes.
theme_question_70539767 <- function(){
theme_bw() %+replace%
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
text = element_text(size = 19, family = "serif"),
axis.ticks = element_blank(),
axis.title.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_text(color = "black"),
legend.position = "top",
legend.text = element_text(size = 10),
legend.key.size = unit(1, "char")
)
}
Add labels to bar chart in r
To make the text show up only on >0, we can subset the data for that layer. To make it show up cleanly above the bars, we can use hjust (the alignment is calculated before the angle rotation, so up-down here is driven by hjust). To make room for those labels, we can adjust the y scale to put more padding on the top (15% here, instead of 5% default).
HIData$A = factor(HIData$A, level = Ainorder)
ggplot(data=HIData, aes(x=A, y=HQ, fill = Category)) +
geom_col() +
geom_text(data=subset(HIData, HQ > 0), aes(label=HQ), angle=90, hjust = -0.2) +
scale_y_continuous(expand = expansion(mult = c(0.05, 0.15))) +
labs(title=paste0("HQ for ID TBD"), y = "HQ", x = NULL) +
theme(panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),
axis.text.x = element_text(angle=90,vjust=0.5, color = Listofcolors),
axis.text.y=element_text(angle=0,vjust=0.5,color = "black"))
R: How to add a label on the right axis in a ggplot barchart?
I find easiest to annotate with geom_text
(you'll need a data frame) or with annotate(geom = "text",...)
. Using annotate is usually safer, as geom_text
likes to create a label for each row (which is fine when you use carefully prepared data frames for annotation).
library(tidyverse)
mtcars$carb<-as.character(mtcars$carb)
mtcars$gear<-as.character(mtcars$gear)
mtcars$carb_labelright<-paste0("label_right",mtcars$carb)
ggplot(mtcars) +
# use geom_col, a convenience wrapper for geom_bar(stat = "identity")
geom_col(aes(fill=gear, y=wt, x=carb),
position="fill", width=.8) +
# you have to turn clipping off
coord_flip(clip = "off") +
annotate(geom = "text", x = unique(mtcars$carb),
label = unique(mtcars$carb_labelright),
y = 1, hjust = 0) +
# you need to increase the legend's margin and make it "transparent"
# otherwise you will cover some labels.
theme(legend.margin = margin(l = 1, unit = "inch"),
legend.background = element_blank())
Created on 2021-10-26 by the reprex package (v2.0.1)
Related Topics
Setting Document Title in Rmarkdown from Parameters
Rmarkdown: How to Change the Font Color
Formatting Reactive Data.Frames in Shiny
Fill Missing Combinations in a Dataframe
Removing the Border of Legend Symbol
How to Learn R as a Programming Language
Reordering Factor Gives Different Results, Depending on Which Packages Are Loaded
How to Fit a Smooth Curve to My Data in R
R - Emulate the Default Behavior of Hist() with Ggplot2 for Bin Width
Select First Element of Nested List
Increase Resolution of Color Scale for Values Close to Zero
Create Empty Data Frame with Column Names by Assigning a String Vector
Creating a Unique Sequence of Dates
R: += (Plus Equals) and ++ (Plus Plus) Equivalent from C++/C#/Java, etc.
How to Map a Vector of Values to Another Vector with My Own Custom Map in R