Issue
Im downloading end of day data using yahoo and plotting graphs. Here an example of part of a script for plotting a bar chart of the accumulated volume (vs the index on the right axis):
p1 = cum_vol.tail(lookback)
pidx = df_idx.tail(lookback)
fig, ax = plt.subplots(figsize=(15, 5))
ax.bar(p1.index, p1, width=1, color='goldenrod', alpha=0.7, label='Accumulated Volume')
# ax.plot(p1.index, p2, color='lightblue', alpha=0.7, label='Decline/Advance Ratio')
ax.set_xlabel('Date')
ax.set_ylabel('Accumulated Volume', color='black')
# Set y-axis limits to the range of accumulated volume
ax.set_ylim(bottom=min(p1), top=max(p1))
# Plot index
ax1 = ax.twinx()
ax1.plot(pidx.index, pidx, 'black', label=idx)
ax1.set_ylabel(idx, color='black')
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax1.get_legend_handles_labels()
ax1.legend(lines + lines2, labels + labels2, loc='upper left')
plt.show()
My problem is that the chart has 2-bar (or more at holidays) gaps at every weekend. In the dataframe, these weekends dates dont exist, but it seems matplotlib, when it plots the timeseries data on the xaxis, includes them with zero as the data.
I imagine the same thing is happening in line charts too? Although they seem to plot correctly, without dropping to zero on weekends.
How can I eliminate this? I imagine two solutions:
- Some parameter that "ignores" weekends and plots friday and monday next to each other. I tried this:
ax.xaxis.set_major_locator(mdates.WeekdayLocator())
but it makes the plot even uglier, bunching up the dates and doing nothing abut the weekend gaps. Without this, the plot looks great (except for the gaps!).
- Reset the index, making the timeseries a column. This seems pretty simple, but it would loose the date labels on the x-axis.
Does anyone have a solution for this?
Thanks!
Solution
You probably should be using custom x-tick labels. That way you an use the index of your data (pandas, numpy array, etc) as the x-axis and still retain your date information.
I've attempted to provide an example below however it doesn't reflect your code since I obviously can't utilize your existing code (because it's incomplete):
import matplotlib.pyplot as plt
import numpy as np
from datetime import datetime
from datetime import timedelta
date = datetime.today()
array = np.array([1,2,3,4,5,6,7,8,9,10])
""" This block generates dates that skip 2 days like a weekend - i didn't configure it to work on weekends but the same theory applies."""
labels = [(date + timedelta(days=int(i))) for i in array]
for i in range(len(labels)) :
if i%5 == 0 :
for j in range(i, len(labels)) :
labels[j] += timedelta(days=2)
labels = [i.strftime("%d/%m/%Y").__str__() for i in labels]
plt.plot(array, array)
""" This is the component that is relevant to you"""
plt.xticks(array, labels, rotation='vertical')
plt.margins(0.2)
plt.subplots_adjust(bottom=0.15)
plt.show()
The following plot is the result:
Please notice that the x-ticks dates skip certain days without any affect on how the graph is displayed.
Answered By - Sten Healey
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.