1

I'm trying to achieve the following:

  1. Create line breaks in the y-axis row text (circled in red in the image below);
  2. Free up space in the left vertical 3rd of the plot.

Text for line break circled in red

I've found I can affect text via theme():

theme(
    axis.text.y = element_text(size = 10),
    plot.title = element_text(face = "bold"),   
)

However, I can't find the correct argument to create line breaks within the following:

axis.text.y = element_text(size = 10)

Am I in the wrong area to accomplish my goal?

Again, the larger goal is to free up space in the left vertical portion of the overall plot. I have no idea how to begin to address that.

Complete code for the plot.

top_customers_tbl %>% 

    # Geometries ----
    ggplot(aes(revenue, bikeshop_name)) +

    geom_segment(aes(xend = 0, yend = bikeshop_name), 
                 color    = palette_light()[1],
                 size     = 1) +
    geom_point(size       = -1,
                   color  = palette_light()[1]) +

    # Labels "inward" hjust special input ----               
    geom_label(aes(label = label_text), 
               hjust     = "inward",
               size      = 3,
               color     = palette_light()[1]) +

    # Formatting ----
    scale_x_continuous(labels = scales::dollar_format(scale = 1e-6, suffix = "M")) +
    labs(
        title    = str_glue("Top {n} Customers"),
        subtitle = str_glue("Top 6 customers = 51% of revenue
                            \nStart: {year(min(bike_orderlines_tbl$order_date))}\nEnd:  {year(max(bike_orderlines_tbl$order_date))}"),
        x        = "Revenue ($M)",
        y        = "Customer"
    ) +

    theme_tq() +
    theme(            
        axis.text.y = element_text(size = 10),
        plot.title  = element_text(face = "bold"),            
    )
Z.Lin
  • 23,077
  • 5
  • 35
  • 71
  • 4
    For (1), try looking into `stringr::str_wrap()` to wrap text to a certain length: https://stackoverflow.com/q/21878974/3277821 – sboysel Nov 25 '19 at 01:04

1 Answers1

0

If you have a clear pattern to the line break...

you can create a new variable with a hard break (\n) at a predefined location. For instance, if you want to break after the first word of a string with three or more words:

# Load mtcars data, isolate car names in new var
  df <- 
    mtcars[1:5,] %>% 
    rownames_to_column(var = 'LongName')

# Add line break in 2nd space (' ') of LongName
  df <-
    df %>%
    mutate(
      Splits = if_else(
        str_count(LongName, '\\S+') > 2,
        str_c(word(LongName,1,1), word(LongName,2,str_count(LongName,'\\S+')), sep = '\n'),
        LongName
      )
    )

The if_else identifies strings longer than two words and then pastes together, using str_c, the first word, and the rest of the string, separated by \n. For short strings, it returns the original string.

>   df$Splits
[1] "Mazda RX4"         "Mazda\nRX4 Wag"    "Datsun 710"        "Hornet\n4 Drive"  
[5] "Hornet Sportabout"

If you have no clear pattern...

You may have to hard code the breaks in a new variable and call those in scale_x_discrete when you plot. For example:

labs = c('Datsun 710','Mazda \n RX4', 'Mazda \n RX4 Wag')

mtcars[1:3,] %>%
  rownames_to_column() %>%
  ggplot(aes(x = rowname, y = mpg)) +
  geom_col() +
  scale_x_discrete(labels = labs) +
  coord_flip() 

The advantage of the first approach is that you don't have to reorder the labels anytime you want to reorder the categories on the axis.

AHart
  • 418
  • 2
  • 10
  • 1
    This solution requires writing out labels and hard-coding where linebreaks should go. This could easily be impractical, especially when data may not be plotted in the same order as you typed up the vector of them. Maybe you can come up with a way that does this programmatically – camille Nov 25 '19 at 03:26
  • Good point. Thanks. I don't see a clear pattern to the breaks specified in the OP, but you're right about the utility of posting a flexible option. I tried to add that in the edits. – AHart Nov 25 '19 at 14:13
  • "# Add line break in 2nd space (' ') of LongName `df %<>%`" Changed aforementioned to: `df%>%` – Josh Nelson Nov 26 '19 at 18:46
  • I'll make the change above. The double assignment `%<>%` operator from `magrittr` serves the same purpose here (`df %<>% mutate()` is equivalent to `df % mutate()`), but you're right that it just adds unneeded complexity here. – AHart Nov 26 '19 at 19:01
  • `scale_y_discrete(labels = function(y) str_wrap(y, width = 10))` I added the code on left to the code in my OP. It spaced everything perfectly. This seems to be the simplest solution. I got the idea from the above link in comments directly under my code example. – Josh Nelson Nov 26 '19 at 19:14
  • @AHart understood on use of ```%<>%``` operator from magrittr. I had thought it was typo. – Josh Nelson Nov 26 '19 at 23:44