Position geom_text on dodged barplot
Is this what you want?
library(ggplot2)
ggplot(bar) +
geom_col(aes(variable, `(all)`, fill = ustanova), position = "dodge") +
geom_text(aes(variable, `(all)`, label = sprintf("%2.1f", `(all)`), group = ustanova),
position = position_dodge(width = .9)) +
coord_flip()
The key is to position = position_dodge(width = .9)
(where .9
is the default width of the bars) instead of position = "dodge"
, which is just a shortcut without any parameter. Additionally you have to set the group=ustanova
aesthetic in geom_text
to dodge the labels by ustanova
(A second option would be to make fill = ustanova
a global aesthetic via ggplot(bar, aes(fill = ustanova))
In ggplot2_2.0.0
you find several examples in ?geom_text
on how to position geom_text
on dodged or stacked bars (the code chunk named "# Aligning labels and bars"
). The Q&A What is the width argument in position_dodge? provides a more thorough description of the topic.
geom_text with dodged barplot AND fill a missing category
This is where complete
from tidyr
can help by filling in those missing values. You also can use vjust
entirely rather than adding to your y values, if you wish.
library(ggplot2)
library(dplyr)
library(tidyr)
df <- count(mtcars, cyl, gear) %>%
complete(cyl, gear, fill = list(n = 0))
ggplot(df, aes(x = factor(cyl), y = n, fill = factor(gear))) +
geom_col(position = position_dodge()) +
geom_text(aes(label = n, y = n), size = 5, vjust = -0.5,
position = position_dodge(width=.9))
Created on 2019-01-17 by the reprex package (v0.2.1)
Aligning geom_text in grouped dodged barplot
The problem is that you are attempting to dodge text on a continuous axis (your flipped x axis is a datetime axis), whereas you probably want this to be a discrete axis. So you can do something like this:
ggplot(total_screening_mensual,
aes(x = factor(Mes), y = n, fill = Sede)) +
geom_col(position = position_dodge(width = 1)) +
scale_fill_brewer(palette = "Pastel1") +
geom_text(aes(label = n, group = Sede),
position = position_dodge(width = 1),
hjust = -0.2, vjust = 0.5, size = 3) +
coord_flip() +
scale_x_discrete(labels = function(x) strftime(x, "%b %Y")) +
labs(title = "Estudios de screening por sede durante 2019",
x = "Mes",
y = "Cantidad de estudios")
Data
total_screening_mensual <-
structure(list(Sede = c("Las Heras", "Las Heras", "Las Heras",
"Las Heras", "Las Heras", "Las Heras", "Las Heras", "Las Heras",
"Las Heras", "Las Heras", "Las Heras", "Las Heras", "Saavedra",
"Saavedra", "Saavedra", "Saavedra", "Saavedra",
"Saavedra", "Saavedra", "Saavedra", "Saavedra",
"Saavedra", "Saavedra", "Saavedra"), Mes = structure(c(1546300800,
1548979200, 1551398400, 1554073200, 1556665200, 1559343600, 1561935600,
1564614000, 1567292400, 1569884400, 1572566400, 1575158400, 1546300800,
1548979200, 1551398400, 1554073200, 1556665200, 1559343600, 1561935600,
1564614000, 1567292400, 1569884400, 1572566400, 1575158400),
class = c("POSIXct", "POSIXt"
), tzone = ""), n = c(54L, 53L, 60L, 56L, 77L, 98L, 103L, 88L,
72L, 75L, 87L, 52L, 50L, 50L, 62L, 89L, 74L, 86L, 103L, 94L,
78L, 91L, 70L, 68L)), row.names = c(NA, -24L
), class = "data.frame")
geom_text how to position the text on bar as I want?
Edit:
The easier solution to get hjust
/vjust
to behave intelligently is to add the group
aesthetic to geom_text
and then hjust
& position
adjust for the group
automatically.
1. Vertical Orientation
ggplot(data) +
geom_bar(
aes(x = name, y = count, fill = week, group = week),
stat='identity', position = 'dodge'
) +
geom_text(
aes(x = name, y = count, label = count, group = week),
position = position_dodge(width = 1),
vjust = -0.5, size = 2
) +
theme_bw()
This gives:
2. Horizontal Orientation
ggplot(data) +
geom_bar(
aes(x = name, y = count, fill = week, group = week),
stat='identity', position = 'dodge'
) +
geom_text(
aes(x = name, y = count, label = count, group = week),
hjust = -0.5, size = 2,
position = position_dodge(width = 1),
inherit.aes = TRUE
) +
coord_flip() +
theme_bw()
This gives:
This is not necessarily the most general way to do this, but you can have a fill
dependent hjust
(or vjust
, depending on the orientation) variable. It is not entirely clear to me how to select the value of the adjustment parameter, and currently it is based on what looks right. Perhaps someone else can suggest a more general way of picking this parameter value.
1. Vertical Orientation
library(dplyr)
library(ggplot2)
# generate some data
data = data_frame(
week = as.factor(rep(c(1, 2), times = 5)),
name = as.factor(rep(LETTERS[1:5], times = 2)),
count = rpois(n = 10, lambda = 20),
hjust = if_else(week == 1, 5, -5),
vjust = if_else(week == 1, 3.5, -3.5)
)
# Horizontal
ggplot(data) +
geom_bar(
aes(x = name, y = count, fill = week, group = week),
stat='identity', position = 'dodge'
) +
geom_text(
aes(x = name, y = count, label = count, vjust = vjust),
hjust = -0.5, size = 2,
inherit.aes = TRUE
) +
coord_flip() +
theme_bw()
Here is what that looks like:
2. Horizontal Orientation
ggplot(data) +
geom_bar(
aes(x = name, y = count, fill = week, group = week),
stat='identity', position = 'dodge'
) +
geom_text(
aes(x = name, y = count, label = count, vjust = vjust),
hjust = -0.5, size = 2,
inherit.aes = TRUE
) +
coord_flip() +
theme_bw()
Here is what that looks like:
Issue with geom_text when using position_dodge
Just one minor change solves the issue. You need to specify group=x
inside your geom_text(aes(...))
call.
ggplot(df) +
geom_bar(aes(z, y, fill=x), position=position_dodge(width=1), stat="identity") +
geom_text(aes(z,y,label=perc, group=x), position=position_dodge(width=1), size=4)
geom_text with dodged barplot
You could try
ggplot(data = data, aes(x = as.factor(m), y = s,fill=pr ,ymax = max(s)*1.1)) +
geom_bar(position = "dodge", stat="identity") +
geom_text(aes(y=s/2,label=paste(round(s,3),"%")),position = position_dodge(.9)) +
scale_x_discrete(labels = function(x) format(as.Date(x), "%m/%y")) +
xlab("m")
The geom_text label does not want to dodge on my bar chart
As far as the grid
graphics system (on which ggplot2
is based) is concerned, text elements have zero width, and therefore cannot be dodged the way that plot columns can. Once solution to this is to use hjust
as an aesthetic mapping:
ggplot(SignupPM, aes(y = count_by_Name, x = month)) +
geom_col(aes(fill = `Membership type`),
position = position_dodge(preserve = 'single')) +
geom_text(aes(label= count_by_Name,
hjust = - 2 * as.numeric(`Membership type`) + 4.3),
vjust = -0.5) +
scale_x_date(breaks = "month", date_labels = "%b %Y") +
scale_fill_manual(values = c("#2381EB", "#8442D1", "#CF07BA"),
name = NULL,
labels = c("Student/Unemployed",
"Full member", "Online member")) +
labs( x = NULL, y = "Number of sign-ups",
title = "Sign-ups per month by membership type") +
theme_classic() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 45, hjust = 0.1, vjust = 0))
Data (as inferred from plot in question)
SignupPM <- structure(list(count_by_Name = c(2L, 1L, 1L, 1L, 2L, 1L, 1L,
2L, 2L, 4L, 2L, 4L, 1L, 4L, 2L, 5L, 5L, 5L, 4L, 1L, 3L, 2L, 8L
), month = structure(c(17928, 17956, 18048, 18078, 18109, 18140,
18170, 18231, 18231, 18262, 18262, 18293, 18293, 18322, 18322,
18353, 18353, 18383, 18383, 18383, 18414, 18414, 18414), class = "Date"),
`Membership type` = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 3L, 1L, 2L,
3L), .Label = c("Membershiptype1", "Membershiptype2", "Membershiptype3"
), class = "factor")), row.names = c(NA, -23L), class = "data.frame")
geom_text ignores position dodge
You just need to specify what your bars represent with the fill argument. Otherwise ggplot doesn't know where to place the text.
Does this solve your problem?
ggplot(data = df, aes(x = Type, y = n, fill=File)) +
geom_col(aes(fill = File), position = position_dodge(width = 0.9)) +
geom_text(aes(label = Perc), position = position_dodge(0.9))
You may also have a look at this question: Position geom_text on dodged barplot
Adding geom_text on dodged barplot not working
You were super close - The one big thing you were forgetting was to include some way of telling the geom_text
layer about the fill
argument (e.g. the dodged bar chart). I added this information into the geom_text
layer using the group
argument in aes
.
library(ggplot2)
library(reshape2)
library(scales)
datos<- melt(datos, id = c("Sistema","Indisp","Total","Max"))
scaleFactor <- max(datos$value) / max(datos$Indisp)
ggplot(datos) +
geom_bar(aes(x=reorder(Sistema,-Indisp), y=value, fill=variable),
stat="identity", position="dodge") +
geom_text(aes(x=reorder(Sistema,-Indisp), y=value/2, label=value, group = variable), #added in group=variable to geom_text
position = position_dodge(width = 0.9)) # experiment with the width value to get the spacing you want
Related Topics
What Are the Differences Between "=" and "≪-" Assignment Operators
Can Dplyr Package Be Used For Conditional Mutating
Fitting a Density Curve to a Histogram in R
What Specifically Are the Dangers of Eval(Parse(...))
Drop Data Frame Columns by Name
Dcast Warning: 'Aggregation Function Missing: Defaulting to Length'
Combine Legends For Color and Shape into a Single Legend
Gather Multiple Sets of Columns
Linear Regression and Group by in R
Cluster Analysis in R: Determine the Optimal Number of Clusters
How to Get Rowsums for Selected Columns in R
Ggplot2 - Annotate Outside of Plot
How to Install an R Package from Source
Count Occurrences of Value in a Set of Variables in R (Per Row)