I am trying to only label a subset of bars in ggplot2. I thought the following would work but it defaults to labelling the centre of the group.
library(tidyverse)
#> -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
#> v ggplot2 3.3.5 v purrr 0.3.4
#> v tibble 3.1.6 v dplyr 1.0.7
#> v tidyr 1.1.4 v stringr 1.4.0
#> v readr 2.1.1 v forcats 0.5.1
#> -- Conflicts ------------------------------------------ tidyverse_conflicts() --
#> x dplyr::filter() masks stats::filter()
#> x dplyr::lag() masks stats::lag()
df <- iris |>
pivot_longer(-Species) |>
count(Species, name, wt = value, name = "value")
df |>
ggplot(aes(x = name, y = value, fill = Species))
geom_col(position = position_dodge())
geom_text(data = df[df$Species == "setosa", ], aes(label = value))

So here I am looking to label the setosa label.
CodePudding user response:
First you have to add position_dodge(width = .9 to dodge the text labels by the same amount as the bars, where .9 is the default width of geom_col.
However, to make the dodging work all groups have to present in your data so you have to use the whole dataframe for geom_text too. To label only one group use e.g. an ifelse to set the labels for the other categories to an empty string.
library(ggplot2)
library(dplyr)
library(tidyr)
df <- iris |>
pivot_longer(-Species) |>
count(Species, name, wt = value, name = "value")
df |>
ggplot(aes(x = name, y = value, fill = Species))
geom_col(position = position_dodge())
geom_text(aes(label = ifelse(Species == "setosa", value, "")),
position = position_dodge(width = .9), vjust = 0)

