python matplotlib "merge" x axis labels for multi index
Question:
I would like to "merge" the first level of multi index, i.e. have a centered "USA" and "EU" instead of the tupples.
Minimal Exmaple
df = pd.DataFrame(data={"region":["USA","USA","EU","EU"], "sctr":["HH","NFC","HH","NFC"], "values":[1,2,3,4]})
df = df.set_index(["region","sctr"])
fig, ax = plt.subplots(1,figsize=(8,6))
df.plot(kind="bar")
plt.xticks(rotation = 0)
plt.show()
Desired output
Using excel, one gets the desired output (almost) by default:
The ideal solution is simple, short and does not require any manual adjustments if more regions / sectrs are added.
Answers:
There are other ways to make the x-axis ticks into two lines: the first line is taken from the multi-index and made into a list; the second line is placed from the multi-index list by the text function. Hiding the existing labels is handled by the plot parameter.
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame(data={"region":["USA","USA","EU","EU"], "sctr":["HH","NFC","HH","NFC"], "values":[1,2,3,4]})
df = df.set_index(["region","sctr"])
fig, ax = plt.subplots(1,figsize=(8,6))
df.plot(kind='bar', xlabel='', ax=ax)
ax.set_xticklabels(df.index.get_level_values(level=1).tolist(), rotation=0)
for container in ax.containers:
for i,child in enumerate(container.get_children()):
if i == 0:
ax.text(child.xy[0]+child.get_width(), -0.08, df.index.get_level_values(level=0)[0], ha='center', transform=ax.transAxes)
elif i == 2:
ax.text(child.xy[0]-(child.get_width()*2), -0.08, df.index.get_level_values(level=0)[2], ha='center', transform=ax.transAxes)
plt.show()
I would like to "merge" the first level of multi index, i.e. have a centered "USA" and "EU" instead of the tupples.
Minimal Exmaple
df = pd.DataFrame(data={"region":["USA","USA","EU","EU"], "sctr":["HH","NFC","HH","NFC"], "values":[1,2,3,4]})
df = df.set_index(["region","sctr"])
fig, ax = plt.subplots(1,figsize=(8,6))
df.plot(kind="bar")
plt.xticks(rotation = 0)
plt.show()
Desired output
Using excel, one gets the desired output (almost) by default:
The ideal solution is simple, short and does not require any manual adjustments if more regions / sectrs are added.
There are other ways to make the x-axis ticks into two lines: the first line is taken from the multi-index and made into a list; the second line is placed from the multi-index list by the text function. Hiding the existing labels is handled by the plot parameter.
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame(data={"region":["USA","USA","EU","EU"], "sctr":["HH","NFC","HH","NFC"], "values":[1,2,3,4]})
df = df.set_index(["region","sctr"])
fig, ax = plt.subplots(1,figsize=(8,6))
df.plot(kind='bar', xlabel='', ax=ax)
ax.set_xticklabels(df.index.get_level_values(level=1).tolist(), rotation=0)
for container in ax.containers:
for i,child in enumerate(container.get_children()):
if i == 0:
ax.text(child.xy[0]+child.get_width(), -0.08, df.index.get_level_values(level=0)[0], ha='center', transform=ax.transAxes)
elif i == 2:
ax.text(child.xy[0]-(child.get_width()*2), -0.08, df.index.get_level_values(level=0)[2], ha='center', transform=ax.transAxes)
plt.show()