Reputation: 865
I'm having a dataframe
df <- data.frame("QuarterYear" = c("2019 Q1","2019 Q1","2019 Q2","2019 Q2","2019 Q3","2019 Q3","2019 Q3"), "Size" = c("Medium","Small","Large","Medium","Large","Medium","Small"),
"percentage" = c(98,2,29,71,13,74,13))
I need to plot a stacked bar chart with labels for each stack
plot_ly(df, x = df$QuarterYear,
y = df$percentage,
type = 'bar',
name = df$Size,
text = paste(df$percentage,"%"),
textposition = 'top',
hoverinfo = 'text',
hovertext = paste('Size: ', df$Size,
'<br> % of Total count: ', paste(df$percentage,"%")),
color = df$Size) %>%
layout(yaxis = list(title = "% of Count", zeroline = FALSE,
showline = FALSE, ticksuffix = "%"), barmode = 'stack',hoverlabel = list(bgcolor= 'white')) %>%
layout(legend = list(orientation = "h",
xanchor = "center",
x = 0.5,
y = -0.13))%>%
add_annotations(text = paste0(df$percentage, "%"),
x = df$QuarterYear,
y = unlist(tapply(df$percentage, df$QuarterYear, FUN=cumsum))-(df$percentage/2),
showarrow = FALSE)
The output obtained is
But 2% is not visible since the size of the stack is smaller to accomodate the value. Is there any possibilities to show the labels only when the value is greater than 5?
Thanks in advance!!
Upvotes: 2
Views: 1856
Reputation: 170
I found this post while trying to put value labels on a stacked bar chart. Some of my values I'm plotting are positive while others are negative, so Mohanasundaram's more-elegant solution didn't work well for me. I'm new to R, but maybe others in a similar situation would find this example useful.
library(plotly)
library(tidyverse)
set.seed(123)
animals<-c('cats','dogs')
qty_decimals<-2
crit<-0.5
# create some random data
df_raw <- data.frame(
my_xval = sample(animals, size=100, replace=TRUE),
my_yval = sample(-10:10 , size=100, replace=TRUE), # can be >0 or <0
my_ycolor=as.factor(sample(1:5 , size=100, replace=TRUE)) ) %>%
group_by(my_xval, my_ycolor) %>%
summarize(my_yval=mean(my_yval), .groups='drop_last')
create_yvallab_pos <-function(df) {
# this function creates a column called -lab_position- that identifies where
# the annotations should go (vertically)
df<-df %>%
mutate(dm_positive = (my_yval>0)) %>%
arrange(my_xval, dm_positive, my_ycolor ) %>%
group_by(my_xval, dm_positive ) %>%
mutate(cumul = cumsum(my_yval),
mylag = lag(cumul),
mylag = replace(mylag,is.na(mylag),0),
lab_position = (cumul+mylag)/2) %>%
ungroup()%>%
select(!c('cumul','mylag','dm_positive')) %>%
arrange(my_xval, my_ycolor )
print(df)
return(df)
}
df<-create_yvallab_pos(df=df_raw)
my_plot<- plotly::plot_ly(data=df, x = ~my_xval,
y = ~my_yval, name = ~my_ycolor, color = ~my_ycolor,
legendgroup = ~my_ycolor, type='bar',showlegend=TRUE) %>%
plotly::layout(barmode='relative')
# v1: this is Mohanasundaram's solution, which works fine when the y-values are either all positive or all negative
my_plot1 <- my_plot %>%
add_annotations(text = ifelse(abs(df$my_yval)>=crit, sprintf(df$my_yval, fmt = paste0('%#.',qty_decimals,'f') ), ''), showarrow=FALSE,
x = ~my_xval, y = unlist(tapply(df$my_yval, df$my_xval, FUN=cumsum))-(df$my_yval/2) ) %>%
plotly::layout( annotations = list(text = 'V1', xref = "paper", yref = "paper", xanchor = "center", yanchor = "bottom", x = 0.5, y = 0.95, showarrow = FALSE) )
# v2: this solution might be better if you have some positive and some negative numbers
my_plot2 <- my_plot %>%
add_annotations(text = ifelse(abs(df$my_yval)>=crit, sprintf(df$my_yval, fmt = paste0('%#.',qty_decimals,'f') ), ''), showarrow=FALSE,
x = ~my_xval, y = ~lab_position) %>%
plotly::layout( annotations = list(text = 'V2', xref = "paper", yref = "paper", xanchor = "center", yanchor = "bottom", x = 0.5, y = 0.95, showarrow = FALSE) )
subplot(my_plot1,my_plot2 )
Upvotes: 0
Reputation: 2949
Use ifelse() function for the annotation text.
plot_ly(df, x = df$QuarterYear,
y = df$percentage,
type = 'bar',
name = df$Size,
text = paste(df$percentage,"%"),
textposition = 'top',
hoverinfo = 'text',
hovertext = paste('Size: ', df$Size,
'<br> % of Total count: ', paste(df$percentage,"%")),
color = df$Size) %>%
layout(yaxis = list(title = "% of Count", zeroline = FALSE,
showline = FALSE, ticksuffix = "%"), barmode = 'stack',hoverlabel = list(bgcolor= 'white')) %>%
layout(legend = list(orientation = "h",
xanchor = "center",
x = 0.5,
y = -0.13))%>%
add_annotations(text = ifelse(df$percentage > 2, paste0(df$percentage, "%"), ""),
x = df$QuarterYear,
y = unlist(tapply(df$percentage, df$QuarterYear, FUN=cumsum))-(df$percentage/2),
showarrow = FALSE)
Upvotes: 1