I am trying to plot a stacked bar chart using pandas dataframe plot method. The x values are floats and I am trying to set xticks at integer intervals with no success. Here is my code
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
data = [[0.0, 4.9, 19.9, 8.1, 0.0], [0.12, 4.5, 27.0, 10.1, 0.0],
[0.24, 2.8, 9.3, 4.6, 0.0], [0.36, 2.2, 9.1, 2.7, 0.0],
[0.48, 2.2, 7.3, 3.1, 0.0], [1.0, 4.9, 26.4, 11.2, 0.0],
[1.12, 5.9, 25.3, 8.7, 0.0], [1.24, 3.7, 13.3, 7.1, 0.0],
[1.3599999999999999, 3.0, 9.5, 3.4, 0.0], [1.48, 3.2, 8.9, 4.7, 0.0],
[2.0, 8.4, 24.8, 20.2, 0.0], [2.12, 9.5, 19.3, 22.5, 0.0],
[2.24, 5.7, 11.8, 6.6, 0.0], [2.36, 4.1, 11.1, 5.1, 0.0],
[2.48, 5.4, 8.0, 4.6, 0.0]]
df = pd.DataFrame(columns = ['xval', 'y1', 'y2', 'y3', 'y4'], data = data)
fig, ax = plt.subplots()
df.plot(x = 'xval', kind = 'bar', ax = ax, stacked = True)
xticks = [x for x in df['xval'] if int(x) == x]
ticklabel = ['{:.1f}'.format(x) for x in xticks]
ax.set_xticks(xticks, labels = ticklabel)
ax.grid()
fig.savefig('mychart.png')
import pandas as pd
from matplotlib import pyplot as plt
data = [
[0.0, 4.9, 19.9, 8.1, 0.0],
[0.12, 4.5, 27.0, 10.1, 0.0],
[0.24, 2.8, 9.3, 4.6, 0.0],
[0.36, 2.2, 9.1, 2.7, 0.0],
[0.48, 2.2, 7.3, 3.1, 0.0],
[1.0, 4.9, 26.4, 11.2, 0.0],
[1.12, 5.9, 25.3, 8.7, 0.0],
[1.24, 3.7, 13.3, 7.1, 0.0],
[1.3599999999999999, 3.0, 9.5, 3.4, 0.0],
[1.48, 3.2, 8.9, 4.7, 0.0],
[2.0, 8.4, 24.8, 20.2, 0.0],
[2.12, 9.5, 19.3, 22.5, 0.0],
[2.24, 5.7, 11.8, 6.6, 0.0],
[2.36, 4.1, 11.1, 5.1, 0.0],
[2.48, 5.4, 8.0, 4.6, 0.0],
]
df = pd.DataFrame(columns=["xval", "y1", "y2", "y3", "y4"], data=data)
fig, ax = plt.subplots()
df.plot(x="xval", kind="bar", ax=ax, stacked=True)
xticks, ticklabels = zip(*[(i, x) for i, x in enumerate(df["xval"]) if x.is_integer()])
ax.set_xticks(xticks, ticklabels)
ax.grid()
fig.savefig("mychart.png")
It seems to me that the issue with the original approach is that the x-axis isn't actually using some real number line (since the bars wouldn't be equally spaced if something like that was happening). You can see this in action by reordering the rows of the data and seeing that the bars and labels will move around, regardless of whether things are sorted (easiest to see without the xticks-rewriting code).
Thus, the xticks should actually be the ordinal numbers of the relevant bars. In this case, the "0.0", "1.0", and "2.0" labels should be at bars 0, 5, and 10, respectively (not 0, 1, and 2).