# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# *This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by <NAME>; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*
#
# *The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*
#

# ## Simple Plots in Matplotlib
#
# Matplotlib is a multi-platform data visualization library built on NumPy arrays.
# It was conceived by <NAME> in 2002, originally as a patch to IPython for enabling interactive MATLAB-style plotting via gnuplot from the IPython command line.
# The Matplotlib package was born shortly aftwards, with version 0.1 released in 2003.
# It received an early boost when it was adopted as the plotting package of choice of the Space Telescope Science Institute (the folks behind the Hubble Telescope), which financially supported Matplotlib’s development and greatly expanded its capabilities.
#
# One of Matplotlib’s most important features is its ability to play well with many operating systems and graphics backends.
# Matplotlib supports dozens of backends and output types, which means you can count on it to work regardless of which operating system you are using or which output format you wish.
# This cross-platform, everything-to-everyone approach has been one of the great strengths of Matplotlib.
# It has led to a large user base, which in turn has led to an active developer base and Matplotlib’s powerful tools and ubiquity within the scientific Python world.

# ### Importing Matplotlib
#
# Just as we use the ``np`` alias for NumPy we will use a standard shorthand for Matplotlib:

import numpy as np
import matplotlib.pyplot as plt
# %matplotlib inline

# This notation probably looks a little unusual. We're not importing the whole of the matploblib package in this case, just the pyplot interface. Matplotlib actually provides two different interfaces, one based on MATLAB, and a second object-oriented interface. We will stick with the MATLAB style interface offered by pyplot for the purposes of this notebook. The magic function below the import tells the notebook that we want static images of any plots, rather than the interactive plots we saw in the example from the previous topic.  

# ### Simple Line Plots

# Perhaps the simplest of all plots is the visualization of a single function $y = f(x)$.
# Here we will take a first look at creating a simple plot of this type.
# For all Matplotlib plots, we start by creating a figure and an axes.
# In their simplest form, a figure and axes can be created as follows:

fig = plt.figure()
ax = plt.axes()

# In Matplotlib, the *figure* (an instance of the class ``plt.Figure``) can be thought of as a single container that contains all the objects representing axes, graphics, text, and labels.
# The *axes* (an instance of the class ``plt.Axes``) is what we see above: a bounding box with ticks and labels, which will eventually contain the plot elements that make up our visualization.
#
# As we're using the MATLAB style interface we technically don't need either `fig` or `ax`, they just allow us to draw the blank graph above. If we want to save our images to a file we will need `fig` later on, however we will never use `ax` in this notebook, and you could just omit it from the code above.
#
# If you wanted to, you could run the code below without having created the figure and axes above. The code should be quite self-explanatory, we create a numpy array of 100 linear spaced points from 0 to 10, and then plot sin(x) at those points. If you reduce the number of points from 100 you will see the graph becomes less smooth, and it you increase it from 100 you will see the graph takes much longer to render.

x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x));

# If we want to create a single figure with multiple lines, we can simply call the ``plot`` function multiple times:

plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x));

# You're not just limited to built-in NumPy functions, you can create graphs of any function you like:

plt.plot(x, x**2)
plt.plot(x,(x**3)/2);

# We can even plot our own data if we store the x and y values in NumPy arrays:

# +
x = np.array([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 250])
y = np.array([0.38, 0.82, 1.27, 1.78, 2.43, 2.77, 3.44, 4.01, 4.60, 5.03, 5.58, 6.17, 6.89, 7.45, 7.83, 14.73])

plt.plot(x,y);
# -

# That's all there is to plotting simple functions in Matplotlib!
# We'll now dive into some more details about how to control the appearance of the axes and lines.

# ### Adjusting the Plot: Line Colors and Styles

# The first adjustment you might wish to make to a plot is to control the line colors and styles.
# The ``plt.plot()`` function takes additional arguments that can be used to specify these.
# To adjust the color, you can use the ``color`` keyword, which accepts a string argument representing virtually any imaginable color.
# The color can be specified in a variety of ways:

plt.plot(x, np.sin(x - 0), color='blue')        # specify color by name
plt.plot(x, np.sin(x - 1), color='g')           # short color code (rgbcmyk)
plt.plot(x, np.sin(x - 2), color='0.75')        # Grayscale between 0 and 1
plt.plot(x, np.sin(x - 3), color='#FFDD44')     # Hex code (RRGGBB from 00 to FF)
plt.plot(x, np.sin(x - 4), color=(1.0,0.2,0.3)) # RGB tuple, values 0 to 1
plt.plot(x, np.sin(x - 5), color='chartreuse'); # all HTML color names supported

# If no color is specified, Matplotlib will automatically cycle through a set of default colors for multiple lines.
#
# Similarly, the line style can be adjusted using the ``linestyle`` keyword:

# +
plt.plot(x, x + 0, linestyle='solid')
plt.plot(x, x + 1, linestyle='dashed')
plt.plot(x, x + 2, linestyle='dashdot')
plt.plot(x, x + 3, linestyle='dotted');

# For short, you can use the following codes:
plt.plot(x, x + 4, linestyle='-')  # solid
plt.plot(x, x + 5, linestyle='--') # dashed
plt.plot(x, x + 6, linestyle='-.') # dashdot
plt.plot(x, x + 7, linestyle=':');  # dotted
# -

# If you would like to be extremely terse, these ``linestyle`` and ``color`` codes can be combined into a single non-keyword argument to the ``plt.plot()`` function:

plt.plot(x, x + 0, '-g')  # solid green
plt.plot(x, x + 1, '--c') # dashed cyan
plt.plot(x, x + 2, '-.k') # dashdot black
plt.plot(x, x + 3, ':r');  # dotted red

# These single-character color codes reflect the standard abbreviations in the RGB (Red/Green/Blue) and CMYK (Cyan/Magenta/Yellow/blacK) color systems, commonly used for digital color graphics.
#
# There are many other keyword arguments that can be used to fine-tune the appearance of the plot; for more details, take a look at the documentation of `plot` here: https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.plot.html

# ### Adjusting the Plot: Axes Limits
#
# Matplotlib does a decent job of choosing default axes limits for your plot, but sometimes it's nice to have finer control.
# The most basic way to adjust axis limits is to use the ``plt.xlim()`` and ``plt.ylim()`` methods:

# +
plt.plot(x, np.sin(x))

plt.xlim(-1, 11)
plt.ylim(-1.5, 1.5);
# -

# A useful related method is ``plt.axis()``which allows you to set the ``x`` and ``y`` limits with a single call, by passing a list which specifies ``[xmin, xmax, ymin, ymax]``:

plt.plot(x, np.sin(x))
plt.axis([-1, 11, -1.5, 1.5]);

# The ``plt.axis()`` method goes even beyond this, allowing you to do things like automatically tighten the bounds around the current plot:

plt.plot(x, np.sin(x))
plt.axis('tight');

# It allows even higher-level specifications, such as ensuring an equal aspect ratio so that on your screen, one unit in ``x`` is equal to one unit in ``y``:

plt.plot(x, np.sin(x))
plt.axis('equal');

# ### Labeling Plots
#
# As the last piece of this subsection, we'll briefly look at the labeling of plots: titles, axis labels, and simple legends.
#
# Titles and axis labels are the simplest such labels—there are methods that can be used to quickly set them:

plt.plot(x, np.sin(x))
plt.title("A Sine Curve")
plt.xlabel("x")
plt.ylabel("sin(x)");

# When multiple lines are being shown within a single axes, it can be useful to create a plot legend that labels each line type.
# Again, Matplotlib has a built-in way of quickly creating such a legend, using the ``plt.legend()`` method.
# Though there are several valid ways of using this, I find it easiest to specify the label of each line using the ``label`` keyword of the plot function:

# +
plt.plot(x, np.sin(x), '-g', label='sin(x)')
plt.plot(x, np.cos(x), ':b', label='cos(x)')

plt.legend();
# -

# As you can see, the ``plt.legend()`` function keeps track of the line style and color, and matches these with the correct label.

# ### Simple Scatter Plots

# Another commonly used plot type is the simple scatter plot, a close cousin of the line plot.
# Instead of points being joined by line segments, here the points are represented individually with a dot, circle, or other shape. If we choose to we can produce scatter plots using the same `plt.plot()` method that we used previously by providing an additional argument:

# +
x = np.linspace(0, 10, 30)
y = np.sin(x)

plt.plot(x, y, 'dk');
# -

# The third argument in the function call is a character that represents the symbol used for the plotting. Just as you can specify options such as ``'-'``, ``'--'`` to control the line style, the marker style has its own set of short string codes. The full list of available symbols can be seen in the documentation of ``plt.plot``, or in Matplotlib's online documentation. Most of the possibilities are fairly intuitive, and we'll show a number of the more common ones here (don't worry too much about the code, its just creating a load of random data points):

rng = np.random.RandomState(0)
for marker in ['o', '.', ',', 'x', '+', 'v', '^', '<', '>', 's', 'd']:
    plt.plot(rng.rand(5), rng.rand(5), marker,
             label="marker='{0}'".format(marker))
plt.legend(numpoints=1)
plt.xlim(0, 1.8);

# For even more possibilities, these character codes can be used together with line and color codes to plot points along with a line connecting them:

plt.plot(x, y, '--ob');

# Additional keyword arguments to ``plt.plot`` specify a wide range of properties of the lines and markers:

plt.plot(x, y, '-p', color='gray',
         markersize=15, linewidth=10,
         markerfacecolor='white',
         markeredgecolor='gray',
         markeredgewidth=2)
plt.ylim(-1.2, 1.2);

# ### Scatter Plots with ``plt.scatter``
#
# A second, more powerful method of creating scatter plots is the ``plt.scatter`` function, which can be used very similarly to the ``plt.plot`` function:

plt.scatter(x, y, marker='o');

# The primary difference of ``plt.scatter`` from ``plt.plot`` is that it can be used to create scatter plots where the properties of each individual point (size, face color, edge color, etc.) can be individually controlled or mapped to data.
#
# Let's show this by creating a random scatter plot with points of many colors and sizes.
# In order to better see the overlapping results, we'll also use the ``alpha`` keyword to adjust the transparency level:

# +
rng = np.random.RandomState(0)
x = rng.randn(100)
y = rng.randn(100)
colors = rng.rand(100)
sizes = 1000 * rng.rand(100)

plt.scatter(x, y, c=colors, s=sizes, alpha=0.3,
            cmap='viridis')
plt.colorbar();  # show color scale
# -

# Notice that the color argument is automatically mapped to a color scale (shown here by the ``colorbar()`` command), and that the size argument is given in pixels.
# In this way, the color and size of points can be used to convey information in the visualization, in order to visualize multidimensional data.
#
# For example, we might use the Iris data from Scikit-Learn, where each sample is one of three types of flowers that has had the size of its petals and sepals carefully measured:

# +
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data.T

fig = plt.figure()
plt.scatter(features[0], features[1], alpha=0.2,
            s=100*features[3], c=iris.target, cmap='viridis')
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1]);
# -

# We can see that this scatter plot has given us the ability to simultaneously explore four different dimensions of the data:
# the (x, y) location of each point corresponds to the sepal length and width, the size of the point is related to the petal width, and the color is related to the particular species of flower.
# Multicolor and multifeature scatter plots like this can be useful for both exploration and presentation of data.
#
# Notice how we also used the line `fig = plt.figure()` in this code block. This is going to allow us to save this image in just a little while.

# ### ``plot`` Versus ``scatter``: A Note on Efficiency
#
# Aside from the different features available in ``plt.plot`` and ``plt.scatter``, why might you choose to use one over the other? While it doesn't matter as much for small amounts of data, as datasets get larger than a few thousand points, ``plt.plot`` can be noticeably more efficient than ``plt.scatter``.
# The reason is that ``plt.scatter`` has the capability to render a different size and/or color for each point, so the renderer must do the extra work of constructing each point individually.
# In ``plt.plot``, on the other hand, the points are always essentially clones of each other, so the work of determining the appearance of the points is done only once for the entire set of data.
# For large datasets, the difference between these two can lead to vastly different performance, and for this reason, ``plt.plot`` should be preferred over ``plt.scatter`` for large datasets.

# ### Saving Figures to File
#
# One nice feature of Matplotlib is the ability to save figures in a wide variety of formats.
# Saving a figure can be done using the ``savefig()`` command.
# For example, to save the previous figure as a PNG file, you can run this:

fig.savefig('my_figure.png')

# We now have a file called ``my_figure.png`` in the current working directory:

# !ls -lh my_figure.png

# To confirm that it contains what we think it contains, let's use the IPython ``Image`` object to display the contents of this file:

from IPython.display import Image
Image('my_figure.png')

# There is signicantly more that you can do with Matplotlib, but hopefully this has given you a useful insight into how to draw simple plots. If you want to learn more about using Matplotlib you can refer to Chapter 4 of the Python Data Science Handbook, and look at the many examples on the Matplotlib website: https://matplotlib.org/3.1.1/index.html

StarcoderdataJupyterScriptsDedupFiltered