Home > Mobile >  Strange matplotlib behaviour when X axis contains negative integers
Strange matplotlib behaviour when X axis contains negative integers

Time:02-25

I'm trying to plot a bar chart where the X axis is days to event (i.e., t-10, t-9, ..., t 10). Below is an example where the X axis contains positive integers. The chart generates correctly.

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

fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
x = pd.DataFrame(np.random.normal(0., 1., size=(250, 2)), columns=['X', 'Y'])
x.plot.bar(y=['X'], width=1, ax=axes[0])
x.plot.bar(y=['Y'], width=1, ax=axes[1])
axes[1].set_xticks(x.index[::5])
axes[1].set_xticklabels(x.index[::5])
plt.tight_layout()
plt.show()
plt.clf()

Positive x axis

However, the chart displays incorrectly when the X axis contains negative values. Any idea why this is happening? Note that all I've changed is add index=[i for i in range(-100, 150)] to the DataFrame.

fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
x = pd.DataFrame(np.random.normal(0., 1., size=(250, 2)), columns=['X', 'Y'], index=[i for i in range(-100, 150)])
x.plot.bar(y=['X'], width=1, ax=axes[0])
x.plot.bar(y=['Y'], width=1, ax=axes[1])
axes[1].set_xticks(x.index[::5])
axes[1].set_xticklabels(x.index[::5])
plt.tight_layout()
plt.savefig(f'images/{label}_first_term_struct.png', dpi=300)
plt.clf()

With negative x axis

CodePudding user response:

The problem is with your commands setting the tick marks. It seems that plotting through pandas does not automatically use the index for the x axis. You can either plot straight through matplotlib, as suggested by @JohanC in a comment on your question, or you can index based on the length of x. Here's one potential approach:

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

def do_plot(x, N):
    fig, axes = plt.subplots(2, 1, figsize=(12, 8), sharex=True)
    x.plot.bar(y=['X'], width=1, ax=axes[0])
    x.plot.bar(y=['Y'], width=1, ax=axes[1])
    axes[1].set_xticks(np.arange(N)[::5])
    axes[1].set_xticklabels(x.index[::5])
    plt.tight_layout()

N = 250
m = -100
x = pd.DataFrame(np.random.normal(0., 1., size=(N, 2)),
                 columns=['X', 'Y'],
                 index=[i for i in range(m, N m)])
do_plot(x, N)

with axes right

  • Related