Error when trying to use a custom function to abbreviate axis labels in ggplot2

266 views Asked by At

I'm using ggplot2 to create a bar chart of data based on survey responses that are exported from Limesurvey; therefore the data has a specific format, and the data column contains some NAs (because of missing responses or because of labeling the levels like in the example below):

plotDf <- data.frame('Profession' = c('a', '-other-', 'c', 'd', 'a', 'g', 'd', 'a', 'c', 'e', '-oth-'))
plotDf[, 1] <- as.character(plotDf[, 1])
attributes(plotDf)$variable.labels[1] <- "What is your profession?"
plotDf[, 1] <- factor(plotDf[, 1], levels=c("a","b","c","d","e","f","g","h"),labels=c("Mayor", "Other elected local government representative", "Municipal or local government administration", "Municipal or local government technical department / engineer", "Staff from Central Authority / Ministry", "Development or Humanitarian Organization", "NGO", "Private sector"))
names(plotDf)[1] <- "Q1"
plotData <- plotDf[, 1]

When plotting this as a bar chart, I want to abbreviate the x axis labels because the response options are very long. I can't use the generic abbreviate function because it omits the vowels; also I want to add three dots ... at the end of abbreviated labels. So I'm trying to use a custom function.

The following is the closest I have come to a solution, based on this earlier post, but it throws an error, see below:

library(ggplot2)
library(stringi)

# Function to shorten label after maxlength
# but only shorten after whole words, and add "..."
shortenLabel <- function(x, maxlength) {
  result <- stri_extract_first_regex(x, paste0("^.{0,", maxlength, "}( |$)"))
  longer <- stri_length(x) > maxlength
  result[longer] <- stri_paste(result[longer], "...") # this produces the error
  result
}

myPlot <- ggplot(plotDf, aes(x=plotData, y=(..count..)/sum(..count..))) + 
  geom_bar(aes(y = (..count..)/sum(..count..), fill = plotData), position = "dodge") + 
  theme_set(theme_light()) +
  geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))), stat = "count", vjust = -0.5, hjust = 0.45) + 
  theme(axis.text.x = element_text(angle = 320, hjust = 0)) +
  scale_y_continuous(labels=scales::percent) +
  ggtitle("What is your profession?") +
  labs(x="", y="Percent", fill="Legend:") +
  scale_x_discrete(drop=FALSE, label=function(x) shortenLabel(x, 15)) + scale_fill_discrete(drop=FALSE)

myPlot 

I'm getting the following error, presumably because of the "NA" (other) responses in the data.

Error in result[longer] <- paste(result[longer], "...", sep = "") :
NAs are not allowed in subscripted assignments 

Is there a way to solve this without having to change the underlying data? Any hints would be much appreciated!

0

There are 0 answers