Skip to content

Instantly share code, notes, and snippets.

@jsundram
Created June 17, 2020 23:19
Show Gist options
  • Save jsundram/ef0543b7c86128faba2c81b887459eaf to your computer and use it in GitHub Desktop.
Save jsundram/ef0543b7c86128faba2c81b887459eaf to your computer and use it in GitHub Desktop.
Histogram of Dates by Day of Year -- https://stackoverflow.com/questions/62391648/
from datetime import datetime, timedelta
import random
import matplotlib.pyplot as plt
import matplotlib.dates as dates
def make_data():
random.seed(0) # Make it repeatable
s = datetime(2020, 1, 1) # Pick a leap year!
days = [s + timedelta(days=i) for i in range(366)]
values = [random.randint(5, 30) for _ in days]
return days, values
def plot_by_day(days, values):
plt.style.use('Solarize_Light2')
fig = plt.figure(figsize=(20, 4), dpi=150)
ax = fig.add_subplot(111)
# add space for a second x-axis (not sure what a good value for bottom is)
fig.subplots_adjust(bottom=0.2)
ax.bar(days, values, align='edge', width=1, linewidth=0, alpha=.8)
ax2 = ax.twiny()
# Time hierarchy: Month / day (1/15), then day (8/22)
# Axis 2: Month
ax2.xaxis.set_major_locator(dates.MonthLocator())
ax2.xaxis.set_major_formatter(dates.DateFormatter('%b'))
# Axis 1: Major (Days 1/15)
ax.xaxis.set_major_locator(dates.DayLocator(bymonthday=[1, 15]))
ax.xaxis.set_major_formatter(dates.DateFormatter('%-d'))
ax.xaxis.set_tick_params(labelsize=8)
ax.set_xlim(days[0], days[-1] + timedelta(hours=23))
# Axis 1: Minor (Days 8 / 22)
ax.xaxis.set_minor_locator(dates.DayLocator(bymonthday=[8, 22]))
ax.xaxis.set_minor_formatter(dates.DateFormatter('%-d'))
ax.xaxis.set_tick_params(which="minor", labelsize=5)
# This is a lot of work just to move the second axis to the bottom
# of the chart (we made room for it with subplots_adjust above)
ax2.set_xlim(ax.get_xlim())
ax2.spines["bottom"].set_position(("axes", -0.05)) # position of text.
ax2.spines["bottom"].set_visible(False) # don't show the axis line
ax2.xaxis.set_ticks_position("bottom")
ax2.xaxis.set_label_position("bottom")
ax2.xaxis.set_tick_params(grid_visible=False) # already have ax's grid
for label in ax2.xaxis.get_ticklabels():
label.set_horizontalalignment('left')
# ax2.patch.set_visible(False)
# for sp in ax2.spines.values(): sp.set_visible(False)
# just go with it and use title twice.
ax.set_title("Day of Year Chart")
ax.set_title(
"{:,} data points".format(len(values)),
loc='right', fontsize=8, color='gray')
ax2.set_xlabel("Date")
ax.set_ylabel("Count")
fig.savefig(
'plot_by_day.png',
facecolor=fig.get_facecolor(),
edgecolor='none'
)
def main():
days, values = make_data()
plot_by_day(days, values)
if __name__ == '__main__':
main()
@jsundram
Copy link
Author

Output looks like this:

plot_by_day.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment