<jupyter_start><jupyter_text>Matplotlib PyplotThe `matplotlib.pyplot` module is a collection of functions that let us get up and running with visualization quickly. Interacting with `pyplot` directly is referred to as the state-machine interface of Matplotlib. This is the first of two approaches that we will take. There are two things that we want to keep in mind with `pyplot`: one, `pyplot` is stateful; and two, `pyplot` tries to set reasonable defaults for us. These two things together can make `pyplot` feel a bit like magic. If you find yourself thinking, "Wait a minute, what is Matplotlib doing here?", then hang tight. When we introduce the next Matplotlib interface, then things may seem a bit more clear.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline
# Let's make our runs consistent
np.random.seed(13)<jupyter_output><empty_output><jupyter_text>DataLet's start by creating some simple curves to plot.<jupyter_code>squares = [x**2 for x in range(11)]
cubes = [x**3 for x in range(11)]
quads = [x**4 for x in range(11)]
squares<jupyter_output><empty_output><jupyter_text>A Simple Plot<jupyter_code>plt.plot(squares)
plt.show()<jupyter_output><empty_output><jupyter_text>This is about as simple as a Matplotlib figure can get. Given `squares`, a Python list of the first 10 squares, Matplotlib gives us a line plot. The `pyplot` module is inferring a lot here. Notice that we did not specify our x and y axes. We didn’t even tell it Matplotlib that we were looking to plot a curve here!Also note that we never instantiated an object from the pyplot module. Instead, we are calling the module directly. First, we feed our data into `plt.plt(squares)`, then we call `plt.show()` to render our figure. If we were to call `plt.show()` again without passing the data back into `plt.plot()`, Matplotlib will not render the figure a second time. That is because Matploglib clears the state of our plot as soon as we call `show`.<jupyter_code># Where did our state go?
plt.show()<jupyter_output><empty_output><jupyter_text>`pyplot` gives us some functions to add titles, axis labels, and more<jupyter_code>plt.plot(squares)
plt.title('Squares Plot')
plt.ylabel(r'$X^{2}$') # note the LaTeX
plt.xlabel('X')
plt.show()<jupyter_output><empty_output><jupyter_text>Plotting Multiple Curves<jupyter_code>plt.plot(squares, label='b = 2')
plt.plot(cubes, label='b = 3')
plt.title('Curves')
plt.ylabel(r'$X^{b}$')
plt.xlabel('X')
plt.legend(loc="upper left")
plt.show()<jupyter_output><empty_output><jupyter_text>Note how the scale of the y-axis changed in this figure. Scale is something that is important to consider whenever we are working with visualizations. Since Matplotlib is keeping the overall dimensions of the figure the same across each of these figures, the curves can look deceptive. Take a close look at the orange curve, $X^{b}$ where $b = 3$. If you were to quickly glance at this figure compared with the previous figure, you might think that the only change we made was the color of the curve! It is always a good idea to think about how relative scale effects our perceptions of visualization. This is also true of color choices, and a host of other design features. Time to take some studio art classes!   Plotting Multiple SubplotsMaybe our plot will be more clear if we separate the two plots into two subplots.<jupyter_code>plt.figure(figsize=(18, 5))
plt.subplot(131)
plt.plot(cubes, label='b = 3')
plt.ylabel(r'$X^{b}$')
plt.xlabel('X')
plt.subplot(132)
plt.plot(squares, label='b = 2')
plt.title('Curves')
plt.xlabel('X')
plt.show()<jupyter_output><empty_output><jupyter_text>Oh no, this is worse! Look at those y-axis scales! And why is the title associated with the second subplot. And we no longer have a legend since these plots don't belong to the `Axes`. Which one of these curves corresponds to $X^{2}$ again?  What happens when we keep adding on?<jupyter_code>plt.figure(figsize=(18, 5))
plt.subplot(131)
plt.plot(cubes, label='b = 3')
plt.ylabel(r'$X^{b}$')
plt.xlabel('X')
plt.subplot(132)
plt.plot(squares, label='b = 2')
plt.title('Curves')
plt.xlabel('X')
plt.subplot(133)
plt.plot(quads, label='b = 4')
plt.xlabel('X')
plt.show()<jupyter_output><empty_output><jupyter_text>This is getting out of hand. Look at all of that repetition! You know how I created this figure? I copied and pasted snippets from the previous figure, and then modified some of the variables. The horror. What if I messed up when editing, or accidentally copied the wrong bit of the previous code? But hey, that title is now centered in the figure.Since this is confusing, let's go back the single plot:<jupyter_code>plt.figure(figsize=(20, 10))
plt.plot(squares, label='b = 2')
plt.plot(cubes, label='b = 3')
plt.plot(quads, label='b = 4')
plt.ylabel(r'$X^{b}$')
plt.xlabel('X')
plt.title('Curves')
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Not All Plots Are Line Plots, Toddthe default plot in `pyplot` is a line plot, but are other functions in the module that we can use.  Scatter Plot<jupyter_code>num_points = 30
x = np.random.rand(num_points)
y = np.random.rand(num_points)
colors = np.random.rand(num_points)
size = (50 * np.random.rand(num_points))**2

print(f'First five entries of size:\n\n{size[:5]}')
plt.figure(figsize=(20, 10))
plt.scatter(x, y, s=size, c=colors, alpha=0.5)
plt.show()<jupyter_output><empty_output><jupyter_text>By using an `alpha=0.5`, we can some transparency. This can be helpful when some of the visual information contained in your plot overlaps.  Bar Plot<jupyter_code>labels = ['Vanilla', 'Chocolate', 'Pistachio', 'Mint']
young_todd = [40, 40, 5, 5]
less_young_todd = [25, 25, 25, 25]

label_loc = np.arange(len(labels))
# What happens if we try to use a list?
#label_loc = [x for x in range(len(labels))]
width = 0.3

plt.figure(figsize=(20, 10))
plt.bar(label_loc - width/2, young_todd, width, label="Baby Todd")
plt.bar(label_loc + width/2, less_young_todd, width, label="Current Todd")

plt.title("Todd's Ice Cream Preferences by Age")
plt.ylabel('Todd Score')
plt.xticks(ticks=label_loc, labels=labels)
plt.legend()<jupyter_output><empty_output><jupyter_text>We have only scratched the surface with these plots. You can really fine tune your visualizations to meet your needs. If you are like me, remembering all of details can be a bit cumbersome. How do I set my x-axis labels, What was that thing about offsetting bars in a bar plot? What are the parameters of `plt.xticks`? Luckily, the docs have our back.<jupyter_code># Check a function's documentation
# plt.xticks?<jupyter_output><empty_output><jupyter_text>Histograms<jupyter_code>x1 = np.random.normal(0, 0.8, 1000)
x2 = np.random.normal(-2, 1, 1000)
x3 = np.random.normal(3, 2, 1000)

kwargs = dict(density='stepfilled', alpha=0.3, bins=50)

plt.figure(figsize=(20, 10))
_ = plt.hist(x1, **kwargs)
_ = plt.hist(x2, **kwargs)
_ = plt.hist(x3, **kwargs)

plt.title("Three Gaussian Distributions")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11223761245180637, 'fraction_numerical': 0.01713551335142082, 'mean_word_length': 5.607547169811321, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '665629', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2475, 'n_tokens_neox': 2267, 'n_words': 866, 'path': 'examples/notebooks/module_02_01_matplotlib_pyplot.ipynb', 'repo_name': 'yngtodd/eleven', 'size': '7003'}