I would like to overlay 2 bar charts in Plotly (R), but cannot figure it out. Can easily be done in ggplot2, but qqplotly renders it incorrectly so I would like to make the chart in plot_ly. Thanks for any suggestions.
data:
df = data.frame(
year = c(2014,2014,2014,2015,2015,2015,2016,2016,2016),
pet = c("dog","cat","bird","dog","cat","bird","dog","cat","bird"),
wt_before = c(56, 25, 26, 10, 19, 41, 16, 17, 13),
wt_after = c(49, 18, 19, 3, 12, 34, 9, 10, 6)
)
ggplot:
ggplot(df)+
geom_bar(aes(year,wt_before,fill=pet),stat="identity",position="dodge",width = 0.9,alpha=0.5)+
geom_bar(aes(year,wt_after,fill=pet),stat="identity",position="dodge",width = 0.9)+
xlab("Year") +
ylab("Weight")
plotly attempt:
plot_ly(df,x= ~year) %>%
add_bars(y= ~wt_before, color = ~pet, alpha = 0.5) %>%
add_bars(y= ~wt_after, color = ~pet, showlegend=FALSE) %>%
layout(xaxis=list(title="Year"),
yaxis=list(title="Weight"))
To make this bar chart a stacked bar chart, go to the property 'Barmode' under 'Bar Size and Spacing' and select 'Stack' as the bar mode from the dropdown list. To set the plot title, go to the 'General' section under the 'Style' menu and type in the plot title within the textbox provided under 'Title'.
A stacked chart is a form of bar chart that shows the composition and comparison of a few variables, either relative or absolute, over time. Also called a stacked bar or column chart, they look like a series of columns or bars that are stacked on top of each other.
As Mike Wise pointed out, it's not a stacked plot but an overlayed bar chart which might lead to weird results (what if the pet gained weight? this kind of information would be lost in the graph). You could plot the weight before and after next to each other, that's more informative and covers all cases.
But let's assume we just want to have a stacked bar chart with multiple identical categorical x-values.
Each bar chart would need to be plotted with "virtual" x-values, i.e a position which is composed of the year (seq
) and the animal (i
):
xaxis_length <- length(unique(df$year))
animal_no <- length(unique(df$pet))
i <- 0
for (animal in unique(df$pet)) {
x <- seq(0,
animal_no * xaxis_length + xaxis_length,
by = xaxis_length + 1) + i
i <- i + 1
}
Those x-values can be used to plot the bars, one bar for the base line, one for the difference (by subtracting the two dataframe columns).
for (animal in unique(df$pet)) {
x <- seq(0,
animal_no * xaxis_length + xaxis_length,
by = xaxis_length + 1) + i
i <- i + 1
p <- add_trace(p,
data=df[df$pet == animal, ],
x = x,
y = ~wt_after,
type = 'bar'
)
p <- add_trace(p,
data=df[df$pet == animal, ],
x = x,
y = df[df$pet == animal, ]$wt_before - df[df$pet == animal, ]$wt_after,
type = 'bar'
)
}
Only for the relevant x-axis ticks the values are shown.
layout(barmode = 'stack',
xaxis=list(ticktext = unique(df$year),
tickvals = seq(1,
xaxis_length * animal_no + xaxis_length,
by = xaxis_length + 1)
),
bargap = 0)
The colors are created by using a list of colors and setting one to half transparent and other not transparent at all.
colors <- c('rgba(97,156,255,',
'rgba(0,186,56,',
'rgba(248,118,109,')
marker=list(color = paste(colors[[animal]],
",0.5)",
sep = "")
Complete code
library(plotly)
df = data.frame(
year = c(2014, 2014, 2014, 2015, 2015, 2015, 2016, 2016, 2016, 2017, 2017, 2017),
pet = c("dog", "cat", "bird", "dog", "cat", "bird", "dog", "cat", "bird", "dog", "cat", "bird"),
wt_before = c(56, 25, 26, 10, 19, 41, 16, 17, 13, 20, 25, 30),
wt_after = c(49, 18, 19, 3, 12, 34, 9, 10, 6, 15, 20, 22)
)
colors <- c('rgba(97,156,255,',
'rgba(0,186,56,',
'rgba(248,118,109,')
xaxis_length <- length(unique(df$year))
animal_no <- length(unique(df$pet))
names(colors) <- unique(df$pet)
p <- plot_ly() %>% layout(barmode = 'stack') %>%
layout(barmode = 'stack',
xaxis=list(ticktext = unique(df$year),
tickvals = seq(1,
xaxis_length * animal_no + xaxis_length,
by = xaxis_length + 1)
),
bargap=0)
i <- 0
for (animal in unique(df$pet)) {
x <- seq(0,
animal_no * xaxis_length + xaxis_length,
by = xaxis_length + 1) + i
i <- i + 1
p <- add_trace(p,
data=df[df$pet == animal, ],
x = x,
y = ~wt_after,
type = 'bar',
name = animal,
marker = list(color = paste(colors[[animal]],
",1)",
sep = "")
),
legendgroup = animal,
text = ~wt_after,
hoverinfo = 'text'
)
p <- add_trace(p,
data=df[df$pet == animal, ],
x = x,
y = df[df$pet == animal, ]$wt_before - df[df$pet == animal, ]$wt_after,
type = 'bar',
name = animal,
marker=list(color = paste(colors[[animal]],
",0.5)",
sep = "")
),
legendgroup = animal,
showlegend = FALSE,
text = ~wt_before,
hoverinfo = 'text'
)
}
p
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With