|
| 1 | +""" |
| 2 | +========================== |
| 3 | +Stock prices over 32 years |
| 4 | +========================== |
| 5 | +
|
| 6 | +.. redirect-from:: /gallery/showcase/bachelors_degrees_by_gender |
| 7 | +
|
| 8 | +A graph of multiple time series that demonstrates custom |
| 9 | +styling of plot frame, tick lines, tick labels, and line graph properties. |
| 10 | +
|
| 11 | +Also demonstrates the custom placement of text labels along the right edge |
| 12 | +as an alternative to a conventional legend. |
| 13 | +
|
| 14 | +Note: The third-party mpl style dufte_ produces similar-looking plots with |
| 15 | +less code. |
| 16 | +
|
| 17 | +.. _dufte: https://github.com/nschloe/dufte |
| 18 | +""" |
| 19 | + |
| 20 | +import numpy as np |
| 21 | +import matplotlib.transforms as mtransforms |
| 22 | +import matplotlib.pyplot as plt |
| 23 | +from matplotlib.cbook import get_sample_data |
| 24 | + |
| 25 | + |
| 26 | +def convertdate(x): |
| 27 | + return np.datetime64(x, 'D') |
| 28 | + |
| 29 | + |
| 30 | +fname = get_sample_data('Stocks.csv', asfileobj=False) |
| 31 | +stock_data = np.genfromtxt(fname, encoding='utf-8', delimiter=',', |
| 32 | + names=True, dtype=None, converters={0: convertdate}) |
| 33 | + |
| 34 | + |
| 35 | +fig, ax = plt.subplots(1, 1, figsize=(6, 8), layout='constrained') |
| 36 | + |
| 37 | +# These are the colors that will be used in the plot |
| 38 | +ax.set_prop_cycle(color=[ |
| 39 | + '#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', |
| 40 | + '#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94', |
| 41 | + '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#dbdb8d', |
| 42 | + '#17becf', '#9edae5']) |
| 43 | + |
| 44 | +stocks_name = ['IBM', 'Apple', 'Microsoft', 'Xerox', 'Amazon', 'Dell', |
| 45 | + 'Alphabet', 'Adobe', 'S&P 500', 'NASDAQ'] |
| 46 | +stocks_ticker = ['IBM', 'AAPL', 'MSFT', 'XRX', 'AMZN', 'DELL', 'GOOGL', |
| 47 | + 'ADBE', 'GSPC', 'IXIC'] |
| 48 | + |
| 49 | +# Manually adjust the label positions vertically (units are points = 1/72 inch) |
| 50 | +y_offsets = {k: 0 for k in stocks_ticker} |
| 51 | +y_offsets['IBM'] = 5 |
| 52 | +y_offsets['AAPL'] = -5 |
| 53 | +y_offsets['AMZN'] = -6 |
| 54 | + |
| 55 | +for nn, column in enumerate(stocks_ticker): |
| 56 | + # Plot each line separately with its own color. |
| 57 | + # don't include any data with NaN. |
| 58 | + good = np.nonzero(np.isfinite(stock_data[column])) |
| 59 | + line, = ax.plot(stock_data['Date'][good], stock_data[column][good], lw=2.5) |
| 60 | + |
| 61 | + # Add a text label to the right end of every line. Most of the code below |
| 62 | + # is adding specific offsets y position because some labels overlapped. |
| 63 | + y_pos = stock_data[column][-1] |
| 64 | + |
| 65 | + # Use an offset transform, in points, for any text that needs to be nudged |
| 66 | + # up or down. |
| 67 | + offset = y_offsets[column] / 72 |
| 68 | + trans = mtransforms.ScaledTranslation(0, offset, fig.dpi_scale_trans) |
| 69 | + trans = ax.transData + trans |
| 70 | + |
| 71 | + # Again, make sure that all labels are large enough to be easily read |
| 72 | + # by the viewer. |
| 73 | + ax.text(np.datetime64('2022-10-01'), y_pos, stocks_name[nn], |
| 74 | + color=line.get_color(), transform=trans) |
| 75 | + |
| 76 | +ax.set_xlim(np.datetime64('1989-06-01'), np.datetime64('2023-01-01')) |
| 77 | + |
| 78 | +fig.suptitle("Technology company stocks prices dollars (1990-2022)", |
| 79 | + ha="center") |
| 80 | + |
| 81 | +# Remove the plot frame lines. They are unnecessary here. |
| 82 | +ax.spines[:].set_visible(False) |
| 83 | + |
| 84 | +# Ensure that the axis ticks only show up on the bottom and left of the plot. |
| 85 | +# Ticks on the right and top of the plot are generally unnecessary. |
| 86 | +ax.xaxis.tick_bottom() |
| 87 | +ax.yaxis.tick_left() |
| 88 | +ax.set_yscale('log') |
| 89 | + |
| 90 | +# Provide tick lines across the plot to help your viewers trace along |
| 91 | +# the axis ticks. Make sure that the lines are light and small so they |
| 92 | +# don't obscure the primary data lines. |
| 93 | +ax.grid(True, 'major', 'both', ls='--', lw=.5, c='k', alpha=.3) |
| 94 | + |
| 95 | +# Remove the tick marks; they are unnecessary with the tick lines we just |
| 96 | +# plotted. Make sure your axis ticks are large enough to be easily read. |
| 97 | +# You don't want your viewers squinting to read your plot. |
| 98 | +ax.tick_params(axis='both', which='both', labelsize='large', |
| 99 | + bottom=False, top=False, labelbottom=True, |
| 100 | + left=False, right=False, labelleft=True) |
| 101 | + |
| 102 | +# Finally, save the figure as a PNG. |
| 103 | +# You can also save it as a PDF, JPEG, etc. |
| 104 | +# Just change the file extension in this call. |
| 105 | +# fig.savefig('percent-bachelors-degrees-women-usa.png', bbox_inches='tight') |
| 106 | +plt.show() |
| 107 | + |
| 108 | +############################################################################# |
| 109 | +# |
| 110 | +# .. admonition:: References |
| 111 | +# |
| 112 | +# The use of the following functions, methods, classes and modules is shown |
| 113 | +# in this example: |
| 114 | +# |
| 115 | +# - `matplotlib.pyplot.subplots` |
| 116 | +# - `matplotlib.axes.Axes.text` |
| 117 | +# - `matplotlib.axis.XAxis.tick_bottom` |
| 118 | +# - `matplotlib.axis.YAxis.tick_left` |
| 119 | +# - `matplotlib.artist.Artist.set_visible` |
0 commit comments