Axis Labels for Each Bar and Each Group in Bar Charts with Dodged Groups

Axis labels for each bar and each group in bar charts with dodged groups

Inspired by @Sandy Muspratt answer on this SO question.

First, create and save as object plot that has no legend and change x axis labels to Female or Male with scale_x_continuous(). Add extra space under the plot with plot.margin= in theme().

library(ggplot2)
library(gridExtra)
p<-ggplot(df,aes(x=group,y=x,fill=gender)) +
geom_bar(stat="identity",position="dodge") +
scale_x_continuous("",breaks=c(-0.25,0.25,0.75,1.25,1.75,2.25,2.75,3.25),
labels=rep(c("Female","Male"),times=4))+
theme(legend.position="none")+
theme(plot.margin = unit(c(1,2,3,1), "lines"))

Now with functions annotation_custom() and textGrob() add labels Study 1, Study 2 under the plot setting x and y coordinates (negative coordinates for y puts labels under the plot).

p1<-p+annotation_custom(grob=textGrob("Study 1"),
xmin=0,xmax=0,ymin=-.2,ymax=-0.2)+
annotation_custom(grob=textGrob("Study 2"),
xmin=1,xmax=1,ymin=-.2,ymax=-0.2)+
annotation_custom(grob=textGrob("Study 3"),
xmin=2,xmax=2,ymin=-.2,ymax=-0.2)+
annotation_custom(grob=textGrob("Study 4"),
xmin=3,xmax=3,ymin=-.2,ymax=-0.2)

To ensure that new labels are plotted, you should convert plot to grobs object and then disable clipping.

gt <- ggplot_gtable(ggplot_build(p1))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)

Sample Image

Changing the axis labels in a group of stacked bar charts

You may try this way. Please let me know if I miss something or I'm wrong with your purpose.

df2 %>% 
group_by(cat1, cat2) %>%
mutate(n = sum(as.integer(value))) %>%
rowwise %>%
mutate(cat1 = paste0(c(cat1, n), collapse = "\n")) %>%
ggplot(aes(x = cat1, y = value, fill = cat3, label = as.integer(value))) +
geom_bar(stat = 'identity', position = 'stack') +
geom_text(position = position_stack(vjust = 0.5), size = 3, color = "#555555") +
geom_errorbar(aes(ymin = agg, ymax = agg)) +
facet_wrap(~ cat2, scales = "free_x", ncol = 6)

Sample Image

Bar graph groups on top of each other rather than superimposing each other

You can adjust the position of groups in geom_bar with the argument position:

geom_bar(stat = "identity", position = position_dodge())

I believe there is no need to use the argument group in ggplot(aes())

If you want to change the color of all bar instead of the outline, change color by fill

Plotting a bar chart with multiple groups

Styling always involves a bit of fiddling and trial (and sometimes error (;). But generally you could probably get quite close to your desired result like so:

library(ggplot2)

ggplot(example, aes(categorical_var, n)) +
geom_bar(position="dodge",stat="identity") +
# Add some more space between groups
scale_x_discrete(expand = expansion(add = .9)) +
# Make axis start at zero
scale_y_continuous(expand = expansion(mult = c(0, .05))) +
# Put facet label to bottom
facet_wrap(~treatment, strip.position = "bottom") +
theme_minimal() +
# Styling via various theme options
theme(panel.spacing.x = unit(0, "pt"),
strip.placement = "outside",
strip.background.x = element_blank(),
axis.line.x = element_line(size = .1),
panel.grid.major.y = element_line(linetype = "dotted"),
panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank())

Sample Image

Produce dodged or side-by-side bar/column charts in Altair?

In case anyone ends up here through google etc, here's the code to bring the bars closer together:

import altair as alt
from vega_datasets import data

source = data.barley()

alt.Chart(source).mark_bar().encode(
alt.X('year:O', axis=None),#axis=alt.Axis(title=None, labels=False, ticks=False)),
alt.Y('sum(yield):Q', axis=alt.Axis(grid=True)),
alt.Facet('site:N',title="Facet title Here",),
color='year:N',
).properties(height=150, width=80).configure_view(
stroke='transparent'
).configure_scale(bandPaddingInner=0,
bandPaddingOuter=0.1,
).configure_header(labelOrient='bottom',
labelPadding = 3).configure_facet(spacing=5
)

Result:

Grouped Bar chart

Thanks to Jake for pointing me in the right direction with his answer!

R - Issues with group order/ ggplot dodge barchart

To reorder the subsegment, assign factor to it and specify the orders in levels.

To reorder the bars within dodged bar chart, use reorder to order the dodged bars with descending size of values.

library(tidyverse)

ggplot(df, aes(factor(subsegment, levels = c("Sub3", "Sub1", "Sub2")),
values,
fill = reorder(company, desc(values)))) +
geom_bar(position="dodge", stat="identity", alpha=0.5) +
labs(x = "subsegment", fill = "company")

reorder_dodged_bar

How to add two tiers of labels for matplotlib stacked group barplot

A simple solution would be to concatenate all the x-values, all the bar-heights and all the tick labels. And then draw them in one go (there is no need for sorting):

import matplotlib.pyplot as plt
import numpy as np

width = 0.25
x = np.arange(1, 7)

fig, ax = plt.subplots(figsize=(10, 6))

tick_labels_1 = ['1'] * len(x)
tick_labels_2 = ['2'] * len(x)
tick_labels_3 = ['3'] * len(x)
shift1_rbc = np.random.uniform(1100, 1200, 6)
shift2_rbc = np.random.uniform(900, 1000, 6)
shift3_rbc = np.random.uniform(1000, 1100, 6)
shift1_plt = np.random.uniform(600, 700, 6)
shift2_plt = np.random.uniform(400, 500, 6)
shift3_plt = np.random.uniform(500, 600, 6)
shift1_ffp = np.random.uniform(250, 300, 6)
shift2_ffp = np.random.uniform(150, 200, 6)
shift3_ffp = np.random.uniform(200, 250, 6)
all_x = np.concatenate([x - 0.4, x - 0.1, x + 0.2])
ax.bar(all_x, np.concatenate([shift1_rbc, shift2_rbc, shift3_rbc]), width,
tick_label=tick_labels_1 + tick_labels_2 + tick_labels_3,
color='crimson', label='red')
ax.bar(all_x, np.concatenate([shift1_plt, shift2_plt, shift3_plt]),
width * .7, color='dodgerblue', label='blue')
ax.bar(all_x, np.concatenate([shift1_ffp, shift2_ffp, shift3_ffp]),
width * .5, color='limegreen', label='green')
ax.margins(x=0.02)
ax.legend(title='Data', bbox_to_anchor=(0.99, 1), loc='upper left')
for spine in ['top', 'right']:
ax.spines[spine].set_visible(False)

ax.set_xticks(x - 0.1001, minor=True)
ax.set_xticklabels(['January', 'February', 'March', 'April', 'May', 'June'], minor=True)
ax.tick_params(axis='x', which='minor', length=0, pad=18)

plt.tight_layout()
plt.show()

bar plot with tick labels

PS: To get 3 layers of labels, one could use newlines:

tick_labels_1 = ['1\n4\n7'] * len(x)
tick_labels_2 = ['2\n5\n8'] * len(x)
tick_labels_3 = ['3\n6\n9'] * len(x)

3 layers of labels



Related Topics



Leave a reply



Submit