keep only some of the Bar labels on the right end side of the plot R

65 Views Asked by At

I have a plot that each bar shows the percentage of changes from one to another. I want to remove the first one that does not have anything to be compared with (study-year).

And place them on the right side, aligned with the axis:

Name | Active_period| site |Time | count
A | last_year| north| mornings |10
A | last_year| south| mornings |20
A | last_year| north| evenings|45
A | last_year| south| evenings|35
A | this_year| north| mornings |80
A | this_year| south| mornings |60
A | this_year| north| evenings|95
A | this_year| south| evenings|120
A | study_year| north| mornings |100
A | study_year| south| mornings |400
A | study_year| north| evenings|220
A | study_year| south| evenings|32
B | last_year| north| mornings |10
B | last_year| south| mornings |45
B | last_year| north| evenings|25
B | last_year| south| evenings|20
B | this_year| north| mornings |300
B | this_year| south| mornings |250
B | this_year| north| evenings|140
B | this_year| south| evenings|20
B | study_year| north| mornings |10
B | study_year| south| mornings |20
B | study_year| north| evenings|10
B | study_year| south| evenings|20

And here is my code. Thanks to @Rui Barradas for helping me with my chart.

theme_my <- function(){ 
  theme_grey(base_size = 10) %+replace%
    theme(
      legend.position = "bottom", 
      axis.text = element_text(size = 11), 
      axis.title = element_text(size = 11, face = "bold"),
      strip.text.x = element_text(size = 12),
      strip.text.y = element_text(size = 12, angle = -90),
      plot.title = element_text(size = 14, face = "bold"),
      plot.subtitle = element_text(size = 13)
    )
}



suppressPackageStartupMessages({
  library(dplyr)
  library(ggplot2)
})
    
data %>%
  mutate(Active_period = factor(Active_period,levels = c("study_year","last_year", "this_year"))) %>%
  group_by(Name, site, Time) %>%
  arrange(Active_period) %>%
  mutate(perc = scales::percent(c(0, diff(count))/dplyr::lag(count, default  = 1))) %>%
  ungroup() %>%
  mutate(Active_period = forcats::fct_rev(Active_period)) %>%
  ggplot(aes(Name, count, fill = Active_period)) +
  geom_col(
    width = 0.8, 
    position = position_dodge2(width = 0.8, preserve = "single")
  ) +
  geom_text(
    position = position_dodge2(width = 0.8, preserve = "single"),
    aes(label = perc, group = Active_period),
    hjust = -0.2
  ) +
  scale_fill_manual(
    name = " ", 
    values = c(study_year ="#5d5c5c", this_year = "#4475aa", last_year = "#333239"),
    limits = c("study_year","last_year", "this_year")
  ) +
  coord_flip() +
  facet_grid(Time ~ site) +
  theme_my()

enter image description here

2

There are 2 best solutions below

4
tjebo On

I think easiest is to create a separate data frame for your text geom and replace the label with "".

library(tidyverse)
df <- read.table(text = "Name | Active_period| site |Time | count
A | last_year| north| mornings |10
A | last_year| south| mornings |20
A | last_year| north| evenings|45
A | last_year| south| evenings|35
A | this_year| north| mornings |80
A | this_year| south| mornings |60
A | this_year| north| evenings|95
A | this_year| south| evenings|120
A | study_year| north| mornings |100
A | study_year| south| mornings |400
A | study_year| north| evenings|220
A | study_year| south| evenings|32
B | last_year| north| mornings |10
B | last_year| south| mornings |45
B | last_year| north| evenings|25
B | last_year| south| evenings|20
B | this_year| north| mornings |300
B | this_year| south| mornings |250
B | this_year| north| evenings|140
B | this_year| south| evenings|20
B | study_year| north| mornings |10
B | study_year| south| mornings |20
B | study_year| north| evenings|10
B | study_year| south| evenings|20", sep = "|", header = T)

new_df <- df %>%
mutate(
  ## clean data from read table entry
  across(everything(), str_trim),
       count = as.integer(count), 
## the rest is like yours
  Active_period = factor(Active_period, levels = c("study_year","last_year", "this_year"))) %>%
group_by(Name, site, Time) %>%
arrange(Active_period) %>%
mutate(perc = scales::percent(c(0, diff(count))/dplyr::lag(count, default  = 1))) %>%
mutate(Active_period = forcats::fct_rev(Active_period))
## note I've removed the ungrouping step

## create the text data frame by replacing the first position with ""
text_df <- 
  new_df %>%
  mutate(perc = c("", perc[2:n()]))

ggplot(new_df, aes(Name, count, fill = Active_period)) +
geom_col(
width = 0.8,
position = position_dodge2(width = 0.8, preserve = "single")
) +
## use the text data frame
geom_text(data = text_df, 
position = position_dodge2(width = 0.8, preserve = "single"),
aes(label = perc, group = Active_period),
hjust = -0.2
) +
scale_fill_manual(
name = " ",
values = c(study_year ="#5d5c5c", this_year = "#4475aa", last_year = "#333239"),
limits = c("study_year","last_year", "this_year")
) +
coord_flip() +
facet_grid(Time ~ site)

Created on 2024-01-12 with reprex v2.0.2

-- PS: The values may be different than your expected result due to different data given

0
Rui Barradas On

The question comes from a problem raised in this other question.
Using the code in the question, just add a y = max(count) in the geom_text layer. See the code comment below.

data %>%
  mutate(Active_period = factor(Active_period,levels = c("study_year","last_year", "this_year"))) %>%
  group_by(Name, site, Time) %>%
  arrange(Active_period) %>%
  mutate(
    perc = scales::percent(c(0, diff(count))/dplyr::lag(count, default  = 1)),
    perc = c("", perc[-1L])
  ) %>%
  ungroup() %>%
  mutate(Active_period = forcats::fct_rev(Active_period)) %>%
  ggplot(aes(Name, count, fill = Active_period)) +
  geom_col(
    width = 0.8, 
    position = position_dodge2(width = 0.8, preserve = "single")
  ) +
  geom_text(
    position = position_dodge2(width = 0.8, preserve = "single"),
    # here is the new value for y, the one
    # that puts the labels near the right side
    # of the plot
    aes(
      y = max(count), 
      label = perc, 
      group = Active_period
    ),
    hjust = 1
  ) +
  scale_fill_manual(
    name = " ", 
    values = c(study_year ="#5d5c5c", this_year = "#4475aa", last_year = "#333239"),
    limits = c("study_year","last_year", "this_year")
  ) +
  coord_flip() +
  facet_grid(Time ~ site) +
  theme_so_q77804382()

Created on 2024-01-18