2

I have the following script for generating a figure with two subplots: one line plot, and one bar plot.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

plt.close('all')

np.random.seed(42)
n = 1000
idx = pd.date_range(end='2020-02-27', periods=n)
df = pd.Series(np.random.randint(-5, 5, n),
               index=idx)
curve = df.cumsum()
bars = df.resample('M').sum()

fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)

curve.plot(ax=ax1)
bars.plot(kind='bar', ax=ax2)
fig.set_tight_layout(True)

I would like to share the x axis between the two subplots, however the command ax2 = fig.add_subplot(212, sharex=ax1) will result in an empty graph for the line plot like the following figure. enter image description here

3
  • 1
    This is a known issue for bar plot, that it plots against the range index and label the ticks using the date index. Commented Feb 27, 2020 at 14:32
  • So there is no solution for it? Commented Feb 27, 2020 at 14:35
  • 2
    I guess so. The problem is aesthetic. Your bars is not equally space, i.e., here it is monthly, but months are not equal in length. So if you respect the time index and plot your bars, for example, at the end dates, they would be uneven spaced. Whereas if you space the bars evenly, then you screw up the time scale for the line plot. Commented Feb 27, 2020 at 14:41

1 Answer 1

2

Here is my version based on Matplotlib (without pandas api for plotting), may be it would be helpful.

I explicitly set the width of bars.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

%matplotlib inline

plt.close('all')

np.random.seed(42)
n = 1000
idx = pd.date_range(end='2020-02-27', periods=n)
df = pd.Series(np.random.randint(-5, 5, n), index=idx)
curve = df.cumsum()
bars = df.resample('M').sum()

#fig = plt.figure()
#ax1 = fig.add_subplot(211)
#ax2 = fig.add_subplot(212)
#curve.plot(ax=ax1)
#bars.plot(kind='bar', ax=ax2)

fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, gridspec_kw={'hspace': 0})
ax1.plot(curve.index, curve.values)
ax2.bar(bars.index, bars.values, width = (bars.index[0] - bars.index[1])/2)

fig.set_tight_layout(True)
_ = plt.xticks(bars.index, bars.index, rotation=90)

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.