ggplotly() resizing to best suite display. Line break in Axis labels?

Hi,

I've been trying to create column bars of top 15 customers revenue and the names of these customers vary in length which is resulting in the plot being "warped" for lack of a better word...

Here is what I mean:

I've seen options to change the text size of the axis or even all the text but reducing the text to a size small enough to render the plots correctly the text becomes unreadable.

I was thinking of possibly adjusting the column sizes and add a line-break in the names so that the name becomes 2 lines instead of 1 long one, but I'm unsure how to proceed.

I'm also open to completely new approaches..

For context, I am using ggplotly() because this is part of a flexdashboard report that I am generating hence I require the ggplotly() to provide use a little interaction.

Below is a sample data set to recreate the issue:

library("tidyverse")
library("plotly")
library("tidytext")
library("formattable")
library("scales")

#  Sample Data
df_sample <- tribble(
  ~custname,               ~Act.Inv.Year, ~Tot.Billed.Amount,
  "COMPANY BOSTON AND A EXTREMELY LONG NAME",             2019,                   425128,
  "COMPANY BOSTON AND A EXTREMELY LONG NAME",             2020,                    26121,
  "COMPANY CHARLESTON AND A EXTREMELY LONG NAME",         2019,                 16280498,
  "COMPANY CHARLESTON AND A EXTREMELY LONG NAME",         2020,                 15564767,
  "COMPANY CHARLESTON AND A EXTREMELY LONG NAME",         2018,                   405844,
  "COMPANY CHARLOTTE AND A EXTREMELY LONG NAME",          2019,                  7838489,
  "COMPANY CHARLOTTE AND A EXTREMELY LONG NAME",          2020,                  3246329,
  "COMPANY CHARLOTTE AND A EXTREMELY LONG NAME",          2018,                  2011286,
  "COMPANY CHICAGO AND A EXTREMELY LONG NAME",            2019,                 39558510,
  "COMPANY CHICAGO AND A EXTREMELY LONG NAME",            2020,                 23725972,
  "COMPANY CHICAGO AND A EXTREMELY LONG NAME",            2018,                 18698035,
  "COMPANY CLEVELAND AND A EXTREMELY LONG NAME",          2019,                  6657149, 
  "COMPANY CLEVELAND AND A EXTREMELY LONG NAME",          2020,                  1536365,
  "COMPANY CLEVELAND AND A EXTREMELY LONG NAME",          2018,                   379691,
  "COMPANY DALLAS AND A EXTREMELY LONG NAME",             2019,                 15143584,
  "COMPANY DALLAS AND A EXTREMELY LONG NAME",             2020,                  8559333,
  "COMPANY DETROIT AND A EXTREMELY LONG NAME",            2019,                  1408708,
  "COMPANY DETROIT AND A EXTREMELY LONG NAME",            2020,                  2197626,
  "COMPANY HOUSTON AND A EXTREMELY LONG NAME",            2019,                  3519787, 
  "COMPANY HOUSTON AND A EXTREMELY LONG NAME",            2020,                  8169534,
  "COMPANY HOUSTON AND A EXTREMELY LONG NAME",            2018,                   241019,
  "COMPANY HOUSTON AND A EXTREMELY LONG NAME INDUSTRIAL", 2019,                    73425,
  "COMPANY INDIANAPOLIS AND A EXTREMELY LONG NAME",       2019,                   282315, 
  "COMPANY INDIANAPOLIS AND A EXTREMELY LONG NAME",       2020,                  4944882,
  "COMPANY LOS ANGELES AND A EXTREMELY LONG NAME",        2019,                 15708881,
  "COMPANY LOS ANGELES AND A EXTREMELY LONG NAME",        2020,                 18918531,
  "COMPANY LOS ANGELES AND A EXTREMELY LONG NAME",        2018,                   686162,
  "COMPANY MIAMI AND A EXTREMELY LONG NAME",              2019,                   147892,
  "COMPANY MIAMI AND A EXTREMELY LONG NAME",              2020,                   352303,
  "COMPANY MIAMI AND A EXTREMELY LONG NAME",              2018,                     5410,
  "COMPANY MINNEAPOLIS",         2019,                 15748282,
  "COMPANY MINNEAPOLIS",        2020,                 12156385,
  "COMPANY MINNEAPOLIS",        2018,                  1227781,
  "COMPANY NEWARK AND A EXTREMELY LONG NAME",             2019,                 39410764,
  "COMPANY NEWARK AND A EXTREMELY LONG NAME",             2020,                 21114220,
  "COMPANY NEWARK AND A EXTREMELY LONG NAME",             2018,                 15915941,
  "COMPANY PEORIA AND A EXTREMELY LONG NAME",             2019,                  4681765,
  "COMPANY PEORIA AND A EXTREMELY LONG NAME",             2020,                  5687418,
  "COMPANY PEORIA AND A EXTREMELY LONG NAME",             2018,                    49056,
  "COMPANY PORTLAND AND A EXTREMELY LONG NAME",           2019,                    36384,
  "COMPANY PORTLAND AND A EXTREMELY LONG NAME",           2020,                    72999,
  "COMPANY ROCHESTER AND A EXTREMELY LONG NAME",          2019,                   678562,
  "COMPANY ROCHESTER AND A EXTREMELY LONG NAME",          2020,                   896877,
  "COMPANY SAN FRANCISCO AND A EXTREMELY LONG NAME",      2019,                   705590,
  "COMPANY SAN FRANCISCO AND A EXTREMELY LONG NAME",      2020,                   507767,
  "COMPANY SEATTLE AND A EXTREMELY LONG NAME",            2019,                  2307699,
  "COMPANY SEATTLE AND A EXTREMELY LONG NAME",            2020,                  2020438,
  "COMPANY SEATTLE AND A EXTREMELY LONG NAME",            2018,                    39603,
  "MISSING NAME",           2019,                   253207,
  "MISSING NAME",           2020,                   215389,
  "MISSING NAME",           2018,                   143926,
  "NULL",                   2018,                   490972,
)
#  Creating the ggplotly 
ggplotly(df_sample %>%  group_by(`Act.Inv.Year`) %>% 
  mutate(
    `Act.Inv.Year` = as.factor(`Act.Inv.Year`),
    `custname` = reorder_within(`custname`,`Tot.Billed.Amount`,`Act.Inv.Year`)
  ) %>% 
  slice_max(`Tot.Billed.Amount`, n =15) %>% 
  ggplot(aes(`custname`,`Tot.Billed.Amount`, fill = `Act.Inv.Year`)) +
  geom_col() +
  theme(legend.position="none") +
  facet_wrap(~`Act.Inv.Year`, scales = "free_y") +
  coord_flip()  +
  scale_x_reordered() +
  scale_y_continuous(expand = c(0,0), labels = dollar) +
  labs(y = "Total Profit $",
       x = "Customer Name")
)

Any ideas on how to handle and adjusting the axis to become readable?

Thanks for the time and help!

Have you tried inserting \n into the names, that usually gives a line break.

library(stringr)

custname <- "COMPANY SEATTLE AND A EXTREMELY LONG NAME"

str_replace(custname, "(?<=\\s[A-Z]{1,10})\\s", "\n")
#> [1] "COMPANY SEATTLE\nAND A EXTREMELY LONG NAME"

Created on 2020-11-11 by the reprex package (v0.3.0)

1 Like

Check out the regex cheat sheet. (?<=xxx) means preceeded by xxx. \\s means a space. [A-Z]{1,10} means between 1 and 10 capital letters. So it's looking for a space that is preceeded by a space and 1-10 capital letters.

You might be able to do it by searching for \\sAND\\s instead (an AND with spaces before and after)

1 Like

Was able to finally make it work adjusting the panel.spacing in theme(), the line break did help alot as well to make it all fit correctly.

ggplotly(df_sample %>%  group_by(`Act.Inv.Year`) %>% filter(
  `Act.Inv.Year` != "2018"
) %>% 
  mutate(
    `Act.Inv.Year` = as.factor(`Act.Inv.Year`),
    `custname` = str_replace(`custname`,"(?<=\\s[A-Z]{1,10})\\s", "\n" ),
    `custname` = reorder_within(`custname`,`Tot.Billed.Amount`,`Act.Inv.Year`)
  ) %>% 
  slice_max(`Tot.Billed.Amount`, n =10) %>% 
  ggplot(aes(`custname`,`Tot.Billed.Amount`, fill = `custname`)) +
  geom_col(width = 0.6) +
  theme(legend.position="none",
        text = element_text(size = 7.75),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        panel.spacing = unit(-7, "lines")
        ) +
  scale_x_reordered() +
  scale_y_continuous(expand = c(0,0), labels = dollar) +
  facet_wrap(~`Act.Inv.Year`, scales = "free") +
  coord_flip()
)
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.

Hi there,

Thanks for the help!
That was what I was thinking but didn't know regex well to come up with that. Do you mind going over the regex and how it knows where to place the line break?

Unfortunately I did implement your suggestion but the problem persists as seen below:

To generate the above and below plow I used:

ggplotly(df_sample %>%  group_by(`Act.Inv.Year`) %>% 
  mutate(
    `Act.Inv.Year` = as.factor(`Act.Inv.Year`),
    `custname` = str_replace(`custname`,"(?<=\\s[A-Z]{1,10})\\s", "\n" ),
    `custname` = reorder_within(`custname`,`Tot.Billed.Amount`,`Act.Inv.Year`)
  ) %>% 
  slice_max(`Tot.Billed.Amount`, n =15) %>% 
  ggplot(aes(`custname`,`Tot.Billed.Amount`, fill = `Act.Inv.Year`)) +
  geom_col(width = 0.6) +
  theme(legend.position="none", text = element_text(size = 8)) +
  facet_wrap(~`Act.Inv.Year`, scales = "free_y") +
  coord_flip()  +
  scale_x_reordered(name = "") +
  scale_y_continuous(expand = c(0,0), labels = dollar, name = "")
)

I believe the issue can also be related to the scale_y_continous() line where it tries to force all to have the same scale. Notice the "free realty" left on the below image on the facets in the extremes which could be used for the central plot.

Not sure how to make them independent.

Any suggestions on how to address that or maybe a different approach all together?

Thanks for the time.

Suggest you do the coord_flip and facet at the end. You might be mixing up x and y