Search code examples
pythonmatplotlibpandas

Pandas plotting two graphs on one scale


I have a line graph that I am highligting at end with a marker(shown as large red diamond here).

I am using two two pandas plot commands to create it. Problem is that I get unexpected results. depending on the length of the data and whether I put the plot for the red diamond first or second I get different results. There does not seem to be a pattern that I can discern. The Correct / Expected result shown below

Correct / Expected result

sometimes i get:

enter image description here

and most of the time with big data sets I get the following warning:

/Users/xxxxx/.virtualenvs/test2/lib/python2.7/site-packages/matplotlib/axes.py:2542: UserWarning: Attempting to set identical left==right results in singular transformations; automatically expanding. left=15727, right=15727 + 'left=%s, right=%s') % (left, right))

The Warning only shows 1st time it happens. Obviously pandas does not like support the plotting of 2 different series with different x scales on the same axis?

Can try code below to generate the graphs, can play around by passing, Series or Dataframes for plot can also reverse the order of the plotting of the red diamond. Can also change the number of data points. One error that I could not recreate here is with the red diamond in middle and blue line only going of to left.

Code:

plot_with_series = False
reverse_order = False
import pandas as pd
dates = pd.date_range('20101115', periods=800)
df =  pd.DataFrame(randn(len(dates)), index = dates, columns = ['A'])
ds = pd.Series(randn(len(dates)), index = dates)
clf()
if plot_with_series:
    if reverse_order: ds.plot()
    ds.tail(1).plot(style='rD', markersize=20)
    if not reverse_order: ds.plot()
else:
    if reverse_order: df.plot(legend=False)
    df.A.tail(1).plot(style='rD', markersize=20,legend=False)
    if not reverse_order: df.plot(legend=False)

The errors/warnings happen from both within IPython or from running the as script from command line. Also constant across 2 latest versions of pandas. Any ideas or obvious problems?


Solution

  • I think pandas by default creates a new plot instead of using the 'active' plot. Capturing the axes and passing it to the next plotting command works fine for me, and is the way to go if you want to reuse your axes.

    Change the last two lines in your example to:

    ax = df.A.tail(1).plot(style='rD', markersize=20,legend=False)
    if not reverse_order: df.plot(legend=False, ax=ax)
    

    Difference is that the axes returned by matplotlib (via pandas) is captured, and passed again with ax=ax. Its also more conform the preferred OO-style for using matplotlib.