I am making a plot with ggplot and I am having some problems with the labels. Here is my code:
ggplot(data = prueba[prueba$Prueba=="lectura",], aes(x = año,
y = Promedio,
group = Tipo,
color = Tipo))+
geom_point(shape = 18,
size = 4, position = position_dodge(0.9)) +
geom_errorbar(aes(ymin = Promedio - Desviacion,
ymax = Promedio + Desviacion,
width = 0.4),
position = position_dodge(0.9),
size = 1.3,
show.legend = F) +
ylim(60,140) +
scale_color_manual(values = c("#A32986",
"#A4589E"),
breaks = c("Nacional",
"Sena")) +
theme(
panel.background = element_rect(fill = "white",
color = "#C6C6C6",
size = 1,
linetype = "solid"),
panel.grid.minor = element_line(size = 0.1,
linetype = "dashed"),
axis.title = element_text(color = "#575756",
size = 13),
axis.text = element_text(color = "#575756",
size = 11),
legend.title = element_blank(),
legend.position = "bottom",
legend.text = element_text(color = "#575756",
size = 13)
) + geom_text(aes(label = round(Promedio)),
position = position_dodge(0.9),
hjust = -0.5,
size = 5,
color = "#575756") +
geom_text(aes(label = paste("(", round(Desviacion), ")")),
color = "#575756",
position = position_dodge(0.9),
hjust = -0.1,
vjust = 2,
size = 5) + xlab(NULL)
The result is
As you see, the labels are not properly aligned. I would like to organize de labels, such that the upper labels are centered around the same axis as the lower labels. Does anyone know how I can do that?
My data can be reproducible by
structure(list(Tipo = c("Sena", "Sena", "Sena", "Sena", "Sena",
"Sena", "Sena", "Sena", "Sena", "Sena", "Sena", "Sena", "Sena",
"Sena", "Sena", "Sena", "Sena", "Sena", "Sena", "Sena", "Sena",
"Sena", "Sena", "Sena", "Sena", "Sena", "Sena", "Sena", "Sena",
"Sena", "Sena", "Sena", "Nacional", "Nacional", "Nacional", "Nacional",
"Nacional", "Nacional", "Nacional", "Nacional", "Nacional", "Nacional",
"Nacional", "Nacional", "Nacional", "Nacional", "Nacional", "Nacional",
"Nacional", "Nacional", "Nacional", "Nacional", "Nacional", "Nacional",
"Nacional", "Nacional", "Nacional", "Nacional", "Nacional", "Nacional",
"Nacional", "Nacional", "Nacional", "Nacional", "Nacional", "Nacional",
"Nacional", "Nacional", "Nacional", "Nacional"), año = structure(c(1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L,
4L, 4L, 4L, 4L, 4L), .Label = c("2016", "2017", "2018", "2019"
), class = "factor"), Promedio = c(96.57, 98.03, 98.51, 100.22,
98.17, 94.57, 98.07, 98.8, 87.38, 101.45, 99, 99.35, 96.11, 98.82,
97.1, 95.8, 97.49, 99.86, 90.59, 97.88, 90.6, 95.13, 97.56, 98.25,
94.03, 89.12, 91.94, 97.21, 94.77, 98.8, 99.04, 98.49, 99, 99,
100, 100, 100, 100, 99, 100, 98, 101, 100, 96, 100, 90, 102,
98, 100, 100, 100, 95, 132, 92, 100, 93, 102, 146, 148, 100,
147, 96, 95, 100, 90, 98, 93, 100, 134, 143), Desviacion = c(19.96,
20.12, 20.27, 19.78, 19.7, 18.21, 19.85, 20.17, 29.58, 22.13,
21.98, 19.35, 20.65, 19.78, 21.17, 25.08, 22.66, 21.62, 20.9,
20.52, 21.32, 18.83, 19.49, 21.09, 21.46, 20.54, 23.93, 21.3,
20.09, 26.99, 19.72, 21.3, 21, 21, 21, 20, 20, 20, 21, 20, 22,
23, 21, 22, 20, 28, 23, 25, 23, 22, 20, 22, 31, 21, 22, 22, 22,
27, 28, 20, 28, 21, 21, 22, 21, 22, 25, 28, 30, 28), Prueba = c("mantenimiento",
"lectura", "competencias", "promoción", "inglés", "ensamblaje",
"razonamiento", "comunicación", "mantenimiento", "promoción",
"comunicación", "lectura", "razonamiento", "inglés", "competencias",
"ensamblaje", "competencias", "comunicación", "mantenimiento",
"inglés", "razonamiento", "promoción", "ensamblaje", "lectura",
"mantenimiento", "razonamiento", "competencias", "lectura", "promoción",
"comunicación", "ensamblaje", "inglés", "competencias", "razonamiento",
"inglés", "promoción", "comunicación", "mantenimiento", "lectura",
"ensamblaje", "competencias", "comunicación", "inglés", "razonamiento",
"lectura", "mantenimiento", "promoción", "ensamblaje", "competencias",
"inglés", "ensamblaje", "promoción", "formar", "mantenimiento",
"lectura", "razonamiento", "comunicación", "enseñar", "evaluar",
"ensamblaje", "evaluar", "promoción", "mantenimiento", "inglés",
"razonamiento", "lectura", "competencias", "comunicación", "formar",
"enseñar")), row.names = c(56L, 57L, 58L, 59L, 60L, 61L, 62L,
63L, 451L, 452L, 453L, 454L, 455L, 456L, 457L, 458L, 934L, 935L,
936L, 937L, 938L, 939L, 940L, 941L, 2036L, 2037L, 2038L, 2039L,
2040L, 2041L, 2042L, 2043L, 24800L, 24801L, 24802L, 24803L, 24804L,
24805L, 24806L, 24807L, 68059L, 68060L, 68061L, 68062L, 68063L,
68064L, 68065L, 68066L, 171328L, 171329L, 171330L, 171331L, 171332L,
171333L, 171334L, 171335L, 171336L, 171337L, 171338L, 339673L,
339674L, 339675L, 339676L, 339677L, 339678L, 339679L, 339680L,
339681L, 339682L, 339683L), class = "data.frame")
Thanks in advance
I came up with the following (note that I did not use all your aesthetics, but should be enough to get the point across for one possible way to solve this).
Putting the labels above at constant height
ggplot(data=subset(df, Prueba=='lectura'), aes(x=año, y=Promedio, group=Tipo, color=Tipo)) +
geom_point(shape=18, size=4, position=position_dodge(0.9)) +
geom_errorbar(aes(
ymin=Promedio-Desviacion, ymax=Promedio+Desviacion, width=0.4
), position=position_dodge(0.9), size=1.3, show.legend=F) +
ylim(60,140) +
geom_text(aes(
label = paste0(round(Promedio), "\n(", round(Desviacion), ")"), y=100),
vjust=-4.2, position=position_dodge(0.9)
)
Giving you this:
I couldn't find a great way to align the text to the right or left of each bar. Since you are using position_dodge
with your dataset, you are unable to use nudge_x
, for example, to move everything "to the right" equally. It's not allowed to use both in the geom. Playing with hjust
kind of works, but you can expect funny things to occur here with the two lines as you already experienced.
Note also that I've combined your two geom_text
calls into one, where you can just use paste0()
or paste()
to combine and "make your own label" on the fly.
vjust
use across the board allows you to put them all at the same height - which I think is what you were referring to, correct?
Again - colors are different than yours, since I did not include your scale_color_manual
and theme
calls.
Putting the Label to the Side, Nudged + Position_dodge
If you want to put the labels to the side, you cannot do this with nudge_x
, since you are unable to combine nudge_x
and position
arguments in geom_text
. A workaround is to create a new variable to use for the label aesthetic based on df$año
, then use that in your aes(...
call in geom_text
:
df$año_new <- as.numeric(df$año) + 0.1 # nudge of "0.1". Had to force numeric, since + does not work on factors
Then you keep everything in the original plot call, but change only the last geom_text
call (note the important addition of hjust=0
, which aligns everything to the left):
geom_text(aes(
x=año_new, y=100,
label = paste0(round(Promedio), "\n(", round(Desviacion), ")")
),
hjust=0,
position=position_dodge(0.9)
)