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!