0

I find the pandas DataFrame.plot method very useful and I especially like the way it formats the x ticks when the x variable is a date. However, there are times when I want to add more complicated marks on top of a plot that was generated using DataFrame.plot. For example, plotting a time series using ax = my_timeseries_df.plot("date", "value) and then calling the fill_between method on the ax object to add confidence intervals. However, when I call a plotting method on an ax object after using it with pandas I can't get any marks to show up.

Here is an example:

enter image description here

And here is the raw code:

import matplotlib.pyplot as plt
import pandas as pd

test = pd.DataFrame({
    "a": pd.date_range(start="2020-04-21", periods=5, freq="D"),
    "b": [1, 2, 3, 4, 5],
    "c": [2, 4, 6, 8, 10],
})
fig, ax = plt.subplots()
test.plot("a", "b", ax=ax)
ax.plot(test.a, test.c, color="red", linewidth=20)

Strangely the y-limit changes after calling ax.plot(...) to accommodate the new points, but the new line does not appear.

I have tried adding %matplotlib inline to the cell but that doesn't help. I could always just bypass DataFrame.plot and use matplotlib for everything, but dealing with time-based x-ticks directly in matplotlib is annoying enough that I would love to let pandas do it for me.

6
  • Please copy and paste the example code into your answer, so we can copy and paste it into our editors. Commented Jun 30, 2020 at 20:43
  • 2
    This question may be relevant: stackoverflow.com/questions/29329725/… Commented Jun 30, 2020 at 20:45
  • @Joooeey good call, I added the raw code. Commented Jun 30, 2020 at 20:47
  • 1
    You could try ax.set_xlim(auto=True) to figure out if the line is plotted on a different part of the x-axis. This can happen when using different modules (Pandas and Matplotlib) that handle the dates differently. Commented Jun 30, 2020 at 20:47
  • No dice with ax.set_xlim(auto=True) unfortunately. Commented Jun 30, 2020 at 20:49

2 Answers 2

1

Use x_compat=True, see docs here:

import matplotlib.pyplot as plt
import pandas as pd

test = pd.DataFrame({
    "a": pd.date_range(start="2020-04-21", periods=5, freq="D"),
    "b": [1, 2, 3, 4, 5],
    "c": [2, 4, 6, 8, 10],
})
fig, ax = plt.subplots()
test.plot("a", "b", ax=ax, x_compat=True)
ax.plot(test.a, test.c, color="red", linewidth=20)

Output:

enter image description here

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

1 Comment

You are correct. It's a bummer that you lose the tick formatting though. The formatting is pretty much the only reason I use the pandas plot instead of just doing it all in matplotlib.
1

Also, for reference, matplotlib has a couple of classes that make it much easier to get closer to the tick formatting that pandas has baked in; AutoDateLocator and ConciseDateFormatter. Although they still don't get you complete parity. You can get the docs here.

import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd

test = pd.DataFrame({
    "a": pd.date_range(start="2020-04-21", periods=5, freq="D"),
    "b": [1, 2, 3, 4, 5],
    "c": [2, 4, 6, 8, 10],
})
fig, ax = plt.subplots()
locator = mdates.AutoDateLocator(minticks=3, maxticks=10)
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)

ax.plot(test.a, test.b)
ax.plot(test.a, test.c, color="red", linewidth=2)

enter image description here

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.