4

I am trying to use a theme to conditionally set the element text based on an attribute ActivitySort. If the value is 0, I would like to bold the text otherwise I would like it stay plain.

require("tidyverse")

task0 <- c('Strategy 1', 'Strategy 1', '2017-04-01', '2020-04-01',0, "Strategy")
task1 <- c('Strategy 1', 'Collect data', '2017-04-01', '2018-04-01',1, "In Progress")
task2 <- c('Strategy 1', 'Clean data', '2018-04-01', '2018-06-01', 1, "Completed")
task3 <- c('Strategy 1', 'Analyse data', '2018-06-01', '2019-04-01',1, "Discontinued")
task10 <- c('Strategy 2', 'Strategy 2', '2017-04-01', '2020-04-01',0, "Strategy")
task11 <- c('Strategy 2', 'Collect data again', '2017-04-01', '2018-04-01',1, "In Progress")
task12 <- c('Strategy 2', 'Clean data again', '2018-04-01', '2018-06-01', 1, "Completed")
task13 <- c('Strategy 2', 'Analyse data again', '2018-06-01', '2019-04-01',1, "Discontinued")
task14 <- c('Strategy 2', 'Write report again', '2019-04-01', '2020-04-01', 1, "Planned")

dataset <- as.data.frame(rbind(task0, task1, task2, task3,task10, task11, task12, task13, task14))
names(dataset) <- c('StrategyName', 'Activity', 'Start', 'End', 'ActivitySort', "Status")


dataset <-  as_tibble(dataset)
dataset <-  dataset  %>% mutate(StartSort = as.Date(Start, "%Y-%m-%d" ))
dataset <-  dataset %>% arrange(desc(StrategyName), desc(ActivitySort), desc(StartSort),Activity,  End)

acts <- c("Strategy", "Completed","In Progress", "Discontinued","Planned")
actcols <- c("#000000","#548235", "#2E75B6", "#BF9000", "#7030A0")
els <-unique(dataset$Activity)

g.gantt <- gather(dataset, "state", "date", 3:4) %>% mutate(date = as.Date(date, "%Y-%m-%d" ), Status=factor(Status, acts[length(acts):1]), Activity=factor(Activity, els))

plot <- ggplot(g.gantt, aes(x = date, y = Activity, color = Status, group=Activity)) +
  geom_line(size = 5) +
  scale_color_manual(values=actcols, name="Status",  breaks = acts, limits = acts) +
  labs(x="Project year", y=NULL, title="Activity timeline")

plot <- plot + facet_grid(rows = vars(StrategyName),  scales="free")


plot <- plot + theme(axis.text.y=  element_text(face=ifelse((dataset$ActivitySort == 0),"bold","plain")))

plot

The code currently bolds the text using ifelse, but the results are not as expected. I am wanting only strategies, items with the black lines and status of strategy to be bolded. Note that currently only the second strategy is bolded where the expectation is for both strategies to be bold.

enter image description here

John Bowyer
  • 1,213
  • 1
  • 15
  • 26

1 Answers1

4

Your problem lies in the fact that you're splitting your data over two facets and you're setting your y axes to free. This means they are not the same. Through ifelse statement, you're just passing on 9 TRUE or FALSE values that are pertaining to an outside data set, i.e. your upper graph gets 9 values (out of which first 4 are FALSE and hence nothing is in bold face), while your lower graph also gets the same 9 values and since the 5th one is TRUE, Strategy 2 is in bold.
You can easily check this by removing the scales="free" part from facet_grid. You should get something like this:

enter image description here

So you'll have to use a custom function that will bold each label based on its content. I've modified the code from here.

bold_labels <- function(breaks) {
  strategy <- filter(dataset, Activity %in% breaks) %>% 
    mutate(check = str_detect(Activity, "Strategy")) %>% 
    pull(check)
  labels <- purrr::map2(
    breaks, strategy,
    ~ if (.y) bquote(bold(.(.x))) else bquote(plain(.(.x)))
  )
  parse(text = labels)
}
plot <- ggplot(g.gantt, aes(x = date, y = Activity, color = Status, group=Activity)) +
  geom_line(size = 5) +
  scale_color_manual(values=actcols, name="Status",  breaks = acts, limits = acts) +
  labs(x="Project year", y=NULL, title="Activity timeline") +
  scale_y_discrete(labels = bold_labels) +
  facet_grid(rows = vars(StrategyName), scales="free_y")
plot

The result:

result

Arienrhod
  • 2,451
  • 1
  • 11
  • 19