How to use condition in geom_text / nudge_y

Viewed 241

I want text labels were above or under of bar cap depending on where is more space for them. Now it's always down which is not always looks good:

example

Here is my code:

library(tidyr)
library(ggplot2)
library(dplyr)
library(stringr)
library(purrr)

numa.nodes <- tibble (
  numa_name = c("numa_01","numa_01","numa_01","numa_01","numa_01","numa_01","numa_02","numa_02","numa_02","numa_02"),
  counter_name =c("cpu01","cpu02","cpu03","cpu04","memory_used","memory_total","cpu01","cpu02","memory_used","memory_total"),
  value = c(sample(0:100,4), sample(0:32,1), 32, sample(0:100,1), sample(0:100,1), sample(0:128,1), 128)
)

 numa.nodes <- numa.nodes %>% add_row(
   numa_name = c("numa_03","numa_03","numa_03","numa_03","numa_03","numa_03","numa_04","numa_04","numa_04","numa_04"),
   counter_name =c("cpu01","cpu02","cpu03","cpu04","memory_used","memory_total","cpu01","cpu02","memory_used","memory_total"),
   value = c(sample(0:100,4), sample(0:32,1), 32, sample(0:100,1), sample(0:100,1), sample(0:128,1), 128)
 )

 
 numa.nodes <- numa.nodes %>% add_row(
   numa_name = c("numa_05","numa_05","numa_05","numa_05","numa_05","numa_05","numa_05"),
   counter_name =c("cpu01","cpu02","cpu03","cpu04","cpu05","memory_used","memory_total"),
   value = c(sample(1:100,5), sample(1:64,1), 64)
 )
 
 
numa.nodes <- numa.nodes %>% mutate(counter_name=factor(counter_name,levels = unique(counter_name),ordered = T))

memory_columns <-  numa.nodes %>% filter(counter_name=='memory_total')
memory_y_scale <- max(memory_columns$value, na.rm = TRUE) + 6




plot_numa = function(num){
  
  df = numa.nodes %>% filter(str_detect(numa_name, num))
  
  cpu_plot = df %>%
    filter(str_detect(counter_name, "cpu")) %>%
    ggplot(aes(x = counter_name)) +
    geom_col(aes(y = 100), fill = "white", color = "black") +
    geom_col(aes(y = value), fill = "#00AFBB", color = "black") +
    geom_text(aes(y = value, label = paste0(value,"%")), nudge_y = 5, color = "black") +
    theme_bw() +
    labs(x = "CPU", y = "")
  
  memory_plot = df %>%
    filter(str_detect(counter_name, "memory")) %>%
    pivot_wider(names_from = counter_name, values_from = value) %>%
    ggplot(aes(x = "") ) +
    geom_col(aes(y = memory_total), fill = "white", color = "black") +
    geom_col(aes(y = memory_used), fill = "#FC4E07", color = "black") +
    geom_text(aes(label = paste(memory_total, "GB"), y = memory_total), nudge_y = 5, color = "black") +
    geom_text(aes(label = paste(memory_used, "GB"), y = memory_used), nudge_y = -3, color = "black") +
    theme_bw() +
    ylim(0, memory_y_scale) +
    labs(x = "Memory", y = "")
  
  ggpubr::ggarrange(cpu_plot, memory_plot, ncol = 2) %>% ggpubr::annotate_figure(top = paste("NUMA",num))
  
}

numa_numbers <- unique(numa.nodes$numa_name) %>% str_remove ("numa_")

ggpubr::ggarrange(plotlist = map(.x = numa_numbers, .f = ~plot_numa(num = .x)))

I tried to change this line:

 geom_text(aes(label = paste(memory_used, "GB"), y = memory_used), nudge_y = -3, color = "black")

to something like that:

     geom_text(aes(label = paste(memory_used, "GB"), y = memory_used),nudge_y =  ifelse( (memory_total-memory_used) > 10, 5, -3)
                                                                                , color = "black")

But I've got an error:

Error in ifelse((memory_total - memory_used) > 10, 5, -3) : 
  object 'memory_total' not found
  1. Is there a better way to print labels optimal way?
  2. What am I doing wrong?
  3. How to change color of label to more contrast ie black on white, white on red?
1 Answers

Think of it this way: The nudge value will be different (potentially) for every observation in your data frame. That means that this is something that should be handled within aes(), where stuff is designed to change with your data, rather than nudge_y, which is designed to be a constant (and complains if used otherwise).

So, the solution is to do away entirely with nudge_y and build your ifelse() statement directly into aes(y=...).

In this case, here's the replacement for that particular geom_text() line:

# to see the same plot posted here, put this at the top of your code
set.seed(7331)
...
# plot code...
...  +

geom_text(aes(
      label = paste(memory_used, "GB"),
      y = ifelse((memory_total-memory_used > 10), memory_used + 5, memory_used - 3)),
      color = "black") +

enter image description here

Related