My code below currently gives me this Matplotlib chart.
I want to modify it such that the left column and the right column of subplots have only one x-axis each at the bottom, instead of 4 x-axes currently per column.
How can I do this? I found some solutions with sharex="col", but it seems like I cannot use it as I have two groups of subplots with different x-axes, and I later join the specific x-axes with "axes.flat1.get_shared_x_axes().join(axes.flat1, axes.flat[3], axes.flat[5], axes.flat[7])".
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.ticker import FuncFormatter
import os
import copy
x = range(10)
y = range(10)
fig, axes = plt.subplots(nrows=4, ncols=2, gridspec_kw={'width_ratios': [1, 1]}, sharex=False, figsize=(11, 7))
def plot_function(axes_object, datatype=1, title=None):
stdlist=[0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001]
#Data to plot. Do not include a total, it will be calculated
index = ["Client 1a", "Client 2a", "Client 1b", "Client 2b", "Client 1c", "Client 2c"]
if(datatype == 2):
data = {'amount': list([0.1, 0.2, 0.3, 0.3, -0.2, 0.3])}
if(datatype == 1):
data = {'amount': list([0.1, 2, 1, 1, -2, 0.3])}
#Store data and create a blank series to use for the waterfall
trans = pd.DataFrame(data=data,index=index)
blank = trans.amount.cumsum().shift(1).fillna(0)
#Get the net total number for the final element in the waterfall
total = trans.sum().amount
trans.loc["net"]= total
blank.loc["net"] = total
#The steps graphically show the levels as well as used for label placement
step = blank.reset_index(drop=True).repeat(3).shift(-1)
step[1::3] = np.nan
blank.loc["net"] = 0
trans=trans.iloc[::-1]
stdlist_plot = copy.deepcopy(stdlist)
stdlist_plot.reverse()
color_positive = 'g'
color_negative = 'r'
colors = []
x = np.array(["A", "B", "C", "D"])
y = np.array([3, 8, 1, 10])
y = list(trans["amount"])
x = list(trans.index.values)
for val in y:
if(val>=0):
colors.append(color_positive)
else:
colors.append(color_negative)
axes_object.barh(x, y, left=blank.iloc[::-1], xerr=stdlist_plot, height = 0.9, color=colors)
#Start label loop
loop = 0
SV_sum = 0
trans=trans.iloc[::-1]
for index, row in trans.iterrows():
if index == 'net':
y = trans.iloc[loop].amount
else:
SV_sum += trans.iloc[loop].amount
y = SV_sum
# Determine if we want a neg or pos offset
if row['amount'] > 0:
#y += pos_offset + stdlist[loop]
pass
else:
#y -= neg_offset + stdlist[loop]
pass
axes_object.annotate("{:,.3f}".format(row['amount'])+"%±"+"{:,.3f}".format(stdlist[loop])+"%",(y+stdlist[loop],6-loop+0.0),ha="left")
loop+=1
axes_object.set_ylim(-0.04,7)
if(title!=None):
axes_object.set_title(title)
plot_function(axes.flat[7], title=None)
plot_function(axes.flat[5], title=None)
plot_function(axes.flat[3], title=None)
plot_function(axes.flat[1], title=None)
plot_function(axes.flat[6], datatype=2, title=None)
plot_function(axes.flat[4], datatype=2, title=None)
plot_function(axes.flat[2], datatype=2, title=None)
plot_function(axes.flat[0], datatype=2, title=None)
axes.flat[0].get_shared_x_axes().join(axes.flat[0], axes.flat[2], axes.flat[4], axes.flat[6])
axes.flat[1].get_shared_x_axes().join(axes.flat[1], axes.flat[3], axes.flat[5], axes.flat[7])
axes.flat[0].xaxis.set_tick_params(which='major', labelbottom=True)
for i in range(8):
axes.flat[i].set_ylim([-0.5, 6.6])
axes.flat[0].set_xlim([-0.1, 1.05])
axes.flat[1].set_xlim([0, 7.2])
plt.tight_layout()
plt.show()
