Why are my bars so thin? I have tried setting width to 1 and they go really thick. I'm not sure what else to try. The default thickness is 0.8, is this how it should look?
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
import numpy as np
working_runs = pd.DataFrame(np.random.uniform(1, 2, 210),
columns=['distance'],
index=pd.date_range('2019-06-01', periods=210, freq='D'))
summed = working_runs['distance'].resample('W').sum()
df = pd.DataFrame(summed)
fig, ax = plt.subplots()
ax.bar(df.index, df.distance)
ax.set_xticks(df.index)
ax.xaxis.set_major_formatter(mdates.DateFormatter("%B %d"))
ax.xaxis.set_minor_formatter(mdates.DateFormatter("%B %d"))
plt.xticks(rotation=90)
fig = ax.get_figure()
fig.set_figheight(10)
fig.set_figwidth(12)
plt.title('2019 Weekly Running Miles')
plt.ylabel('Distance /m')
fig.savefig("output.png")
I tried changing it like this:
ax.bar(df.index, df.distance,width=1)
0.9 does not look any different and 1.0 looks like this:
I can confirm the weird behaviour, when setting width to something less than 1.0, it seems to be interpreted as a width for one day. When setting it to 1.0 or higher, it gets interpreted as a width for one week.
It seems to be a problem with how pandas and matplotlib work together.
A workaround could be to use an edgecolor
as in ax.bar(df.index, df.distance, width=1, edgecolor='white')
as in:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
import numpy as np
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
working_runs = pd.DataFrame(np.random.uniform(1, 2, 210),
columns=['distance'],
index=pd.date_range('2019-06-01', periods=210, freq='D'))
summed = working_runs['distance'].resample('W').sum()
df = pd.DataFrame(summed)
fig, ax = plt.subplots()
ax.bar(df.index, df.distance, width=1, edgecolor='white')
ax.xaxis.set_major_formatter(mdates.DateFormatter("%B %d"))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=7))
ax.autoscale(enable=True, axis='x', tight=True)
plt.xticks(rotation=90)
plt.title('2019 Weekly Running Miles')
plt.ylabel('Distance /m')
plt.show()
I experimented with staying in pandas using df.plot.bar(y='distance', width=0.9, ax=ax)
. Formatting the dates can be accomplished by explicitly converting the index
to a list of labels. Also in this case, the plot would look nicer using width=1
and edgecolor='white'
.
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import pandas as pd
import numpy as np
working_runs = pd.DataFrame(np.random.uniform(1, 2, 210),
columns=['distance'],
index=pd.date_range('2019-06-01', periods=210, freq='D'))
summed = working_runs['distance'].resample('W').sum()
df = pd.DataFrame(summed)
fig, ax = plt.subplots()
df.plot.bar(y='distance', width=0.9, ax=ax)
plt.xticks(range(len(df.index)),
[t.to_pydatetime().strftime("%b %d") for t in df.index],
rotation=90)
plt.title('2019 Weekly Running Miles')
plt.ylabel('Distance /m')
plt.show()