# Class 4: Plotting with Matplotlib

Matplotlib is a powerful plotting module that is part of Python's standard library. The website for matplotlib is at http://matplotlib.org/. And you can find a bunch of examples at the following two locations: http://matplotlib.org/examples/index.html and http://matplotlib.org/gallery.html.

Matplotlib contains a module called pyplot that was written to provide a Matlab-style plotting interface.


```python
# Import matplotlib.pyplot
import matplotlib.pyplot as plt
```

## An Introductory Example

Create a plot of the sine function for x values between -6 and 6. Add axis labels and a title.


```python
# Import numpy as np
import numpy as np

# Create an array of x values from -6 to 6
x = np.linspace(-6,6,1000)

# Create a variable y equal to the sine of x
y = np.sin(x)

# Use the plot function to plot x on the horizontal axis and y on the vertical axis
plt.plot(x,y)

# Add a title and axis labels
plt.title('sin(x)')
plt.xlabel('x')
plt.ylabel('y')
```

## Style Sheets and Magic Commands

Plots made using Matplotlib are highly customizable. Users can issue commands to control the limits of the axes, location of axis ticks, labels associated with axis ticks, and the color, thickness, opacity, and style of plotted data points. 

But as a starting-point, Matplotlib uses a *style sheet* to establish initial plot settings until the user specifies different alternatives. The release of Matplotlib 2.0 included a major change in the default syle and the new default doesn't appeal to me.


Next, when we change from the default ploting style, it disrupts how Jupyter formats and displays plots. To fix this, we have to issue a command to be interpretted by Jupyter -- called a *magic* command. A magic command is preceded by a `%` character. Magics are *not* Python and will create errors if used in a Python program outside of the Jupyter notebook (i.e., if you are running Python in IDLE or executing a Python script form the command line, make sure to comment out lines with magics).


```python
# Set the Matplotlib style sheet to 'classic'
plt.style.use('classic')

# Magic command for the Jupyter Notebook to display plots in the notebook
%matplotlib inline

# Use the plot function to plot the sine function
plt.plot(x,y)

# Add a title and axis labels
plt.title('sin(x)')
plt.xlabel('x')
plt.ylabel('y')
```

The matplotlib attribute `plt.style.available` stores as a `list` the default sstyle sheets that you can choose from. Here's a gallery of the different sytles compared with each other. Aside from `classic`, other styles that I think look nice include: `bmh`, `ggplot`, and `seaborn`. But try them all out and see what you like!


```python
#Print the available matplotlib style sheets. PROVIDED
print(plt.style.available)
```

    ['Solarize_Light2', '_classic_test_patch', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn', 'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark', 'seaborn-dark-palette', 'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'tableau-colorblind10']


## The `plot` Function

The `plot` function creates a two-dimensional plot of one variable against another. 


```python
# Use the help function to see the documentation for plt.plot()
help(plt.plot)
```

    Help on function plot in module matplotlib.pyplot:
    
    plot(*args, scalex=True, scaley=True, data=None, **kwargs)
        Plot y versus x as lines and/or markers.
        
        Call signatures::
        
            plot([x], y, [fmt], *, data=None, **kwargs)
            plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
        
        The coordinates of the points or line nodes are given by *x*, *y*.
        
        The optional parameter *fmt* is a convenient way for defining basic
        formatting like color, marker and linestyle. It's a shortcut string
        notation described in the *Notes* section below.
        
        >>> plot(x, y)        # plot x and y using default line style and color
        >>> plot(x, y, 'bo')  # plot x and y using blue circle markers
        >>> plot(y)           # plot y using x as index array 0..N-1
        >>> plot(y, 'r+')     # ditto, but with red plusses
        
        You can use `.Line2D` properties as keyword arguments for more
        control on the appearance. Line properties and *fmt* can be mixed.
        The following two calls yield identical results:
        
        >>> plot(x, y, 'go--', linewidth=2, markersize=12)
        >>> plot(x, y, color='green', marker='o', linestyle='dashed',
        ...      linewidth=2, markersize=12)
        
        When conflicting with *fmt*, keyword arguments take precedence.
        
        
        **Plotting labelled data**
        
        There's a convenient way for plotting objects with labelled data (i.e.
        data that can be accessed by index ``obj['y']``). Instead of giving
        the data in *x* and *y*, you can provide the object in the *data*
        parameter and just give the labels for *x* and *y*::
        
        >>> plot('xlabel', 'ylabel', data=obj)
        
        All indexable objects are supported. This could e.g. be a `dict`, a
        `pandas.DataFrame` or a structured numpy array.
        
        
        **Plotting multiple sets of data**
        
        There are various ways to plot multiple sets of data.
        
        - The most straight forward way is just to call `plot` multiple times.
          Example:
        
          >>> plot(x1, y1, 'bo')
          >>> plot(x2, y2, 'go')
        
        - Alternatively, if your data is already a 2d array, you can pass it
          directly to *x*, *y*. A separate data set will be drawn for every
          column.
        
          Example: an array ``a`` where the first column represents the *x*
          values and the other columns are the *y* columns::
        
          >>> plot(a[0], a[1:])
        
        - The third way is to specify multiple sets of *[x]*, *y*, *[fmt]*
          groups::
        
          >>> plot(x1, y1, 'g^', x2, y2, 'g-')
        
          In this case, any additional keyword argument applies to all
          datasets. Also this syntax cannot be combined with the *data*
          parameter.
        
        By default, each line is assigned a different style specified by a
        'style cycle'. The *fmt* and line property parameters are only
        necessary if you want explicit deviations from these defaults.
        Alternatively, you can also change the style cycle using
        :rc:`axes.prop_cycle`.
        
        
        Parameters
        ----------
        x, y : array-like or scalar
            The horizontal / vertical coordinates of the data points.
            *x* values are optional and default to ``range(len(y))``.
        
            Commonly, these parameters are 1D arrays.
        
            They can also be scalars, or two-dimensional (in that case, the
            columns represent separate data sets).
        
            These arguments cannot be passed as keywords.
        
        fmt : str, optional
            A format string, e.g. 'ro' for red circles. See the *Notes*
            section for a full description of the format strings.
        
            Format strings are just an abbreviation for quickly setting
            basic line properties. All of these and more can also be
            controlled by keyword arguments.
        
            This argument cannot be passed as keyword.
        
        data : indexable object, optional
            An object with labelled data. If given, provide the label names to
            plot in *x* and *y*.
        
            .. note::
                Technically there's a slight ambiguity in calls where the
                second label is a valid *fmt*. ``plot('n', 'o', data=obj)``
                could be ``plt(x, y)`` or ``plt(y, fmt)``. In such cases,
                the former interpretation is chosen, but a warning is issued.
                You may suppress the warning by adding an empty format string
                ``plot('n', 'o', '', data=obj)``.
        
        Returns
        -------
        list of `.Line2D`
            A list of lines representing the plotted data.
        
        Other Parameters
        ----------------
        scalex, scaley : bool, default: True
            These parameters determine if the view limits are adapted to the
            data limits. The values are passed on to `autoscale_view`.
        
        **kwargs : `.Line2D` properties, optional
            *kwargs* are used to specify properties like a line label (for
            auto legends), linewidth, antialiasing, marker face color.
            Example::
        
            >>> plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2)
            >>> plot([1, 2, 3], [1, 4, 9], 'rs', label='line 2')
        
            If you make multiple lines with one plot call, the kwargs
            apply to all those lines.
        
            Here is a list of available `.Line2D` properties:
        
            Properties:
            agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array
            alpha: float or None
            animated: bool
            antialiased or aa: bool
            clip_box: `.Bbox`
            clip_on: bool
            clip_path: Patch or (Path, Transform) or None
            color or c: color
            contains: unknown
            dash_capstyle: {'butt', 'round', 'projecting'}
            dash_joinstyle: {'miter', 'round', 'bevel'}
            dashes: sequence of floats (on/off ink in points) or (None, None)
            data: (2, N) array or two 1D arrays
            drawstyle or ds: {'default', 'steps', 'steps-pre', 'steps-mid', 'steps-post'}, default: 'default'
            figure: `.Figure`
            fillstyle: {'full', 'left', 'right', 'bottom', 'top', 'none'}
            gid: str
            in_layout: bool
            label: object
            linestyle or ls: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
            linewidth or lw: float
            marker: marker style string, `~.path.Path` or `~.markers.MarkerStyle`
            markeredgecolor or mec: color
            markeredgewidth or mew: float
            markerfacecolor or mfc: color
            markerfacecoloralt or mfcalt: color
            markersize or ms: float
            markevery: None or int or (int, int) or slice or List[int] or float or (float, float) or List[bool]
            path_effects: `.AbstractPathEffect`
            picker: unknown
            pickradius: float
            rasterized: bool or None
            sketch_params: (scale: float, length: float, randomness: float)
            snap: bool or None
            solid_capstyle: {'butt', 'round', 'projecting'}
            solid_joinstyle: {'miter', 'round', 'bevel'}
            transform: `matplotlib.transforms.Transform`
            url: str
            visible: bool
            xdata: 1D array
            ydata: 1D array
            zorder: float
        
        See Also
        --------
        scatter : XY scatter plot with markers of varying size and/or color (
            sometimes also called bubble chart).
        
        Notes
        -----
        **Format Strings**
        
        A format string consists of a part for color, marker and line::
        
            fmt = '[marker][line][color]'
        
        Each of them is optional. If not provided, the value from the style
        cycle is used. Exception: If ``line`` is given, but no ``marker``,
        the data will be a line without markers.
        
        Other combinations such as ``[color][marker][line]`` are also
        supported, but note that their parsing may be ambiguous.
        
        **Markers**
        
        =============    ===============================
        character        description
        =============    ===============================
        ``'.'``          point marker
        ``','``          pixel marker
        ``'o'``          circle marker
        ``'v'``          triangle_down marker
        ``'^'``          triangle_up marker
        ``'<'``          triangle_left marker
        ``'>'``          triangle_right marker
        ``'1'``          tri_down marker
        ``'2'``          tri_up marker
        ``'3'``          tri_left marker
        ``'4'``          tri_right marker
        ``'s'``          square marker
        ``'p'``          pentagon marker
        ``'*'``          star marker
        ``'h'``          hexagon1 marker
        ``'H'``          hexagon2 marker
        ``'+'``          plus marker
        ``'x'``          x marker
        ``'D'``          diamond marker
        ``'d'``          thin_diamond marker
        ``'|'``          vline marker
        ``'_'``          hline marker
        =============    ===============================
        
        **Line Styles**
        
        =============    ===============================
        character        description
        =============    ===============================
        ``'-'``          solid line style
        ``'--'``         dashed line style
        ``'-.'``         dash-dot line style
        ``':'``          dotted line style
        =============    ===============================
        
        Example format strings::
        
            'b'    # blue markers with default shape
            'or'   # red circles
            '-g'   # green solid line
            '--'   # dashed line with default color
            '^k:'  # black triangle_up markers connected by a dotted line
        
        **Colors**
        
        The supported color abbreviations are the single letter codes
        
        =============    ===============================
        character        color
        =============    ===============================
        ``'b'``          blue
        ``'g'``          green
        ``'r'``          red
        ``'c'``          cyan
        ``'m'``          magenta
        ``'y'``          yellow
        ``'k'``          black
        ``'w'``          white
        =============    ===============================
        
        and the ``'CN'`` colors that index into the default property cycle.
        
        If the color is the only part of the format string, you can
        additionally use any  `matplotlib.colors` spec, e.g. full names
        (``'green'``) or hex strings (``'#008000'``).
    


### Example

Create a plot of $f(x) = x^2$ with $x$ between -2 and 2.
* Set the linewidth to 3 points
* Set the line opacity (alpha) to 0.6
* Set axis labels and title
* Add a grid to the plot


```python
# Create an array of x values from -2 to 2
x = np.linspace(-2,2,1000)

# Create a variable y equal to x squared
y = x**2

# Use the plot function to plot the line
plt.plot(x,y,linewidth=3,alpha = 0.6)

# Add a title and axis labels
plt.title('$f(x) = x^2$')
plt.xlabel('x')
plt.ylabel('y')

# Add grid
plt.grid()
```

### Example

Create plots of the functions $f(x) = \log x$ (natural log) and $g(x) = 1/x$ between 0.01 and 5
* Make the line for $log(x)$ solid blue
* Make the line for $1/x$ dashed magenta
* Set the linewidth of each line to 3 points
* Set the line transparency (alpha) for each line to 0.6
* Set the limits for the $x$-axis to (0,5)
* Set the limits for the $y$-axis to (-2,5)
* Set axis labels and title
* Add a legend
* Add a grid to the plot


```python
# Create an array of x values from 0.01 to 5
x = np.linspace(0.01,5,1000)

# Create y variables
y1 = np.log(x)
y2 = 1/x

# Use the plot function to plot the lines
plt.plot(x,y1,'b-',lw=3,alpha = 0.6,label='$\log(x)$')
plt.plot(x,y2,'m--',c='m',linestyle='--',linewidth=3,alpha = 0.6,label='$1/x$')

# Add a title and axis labels
plt.title('Two functions')
plt.xlabel('x')
plt.ylabel('y')

# Set axis limits
plt.xlim([0,5])
plt.ylim([-2,4])

# Make legend
plt.legend(loc='lower right',ncol=2)

# Add grid
plt.grid()
```

### Example


Consider the linear regression model:
\begin{align}
y_i = \beta_0 + \beta_1 x_i + \epsilon_i
\end{align}
where $x_i$ is the independent variable, $\epsilon_i$ is a random regression error term, $y_i$ is the dependent variable and $\beta_0$ and $\beta_1$ are constants.

Let's simulate the model
* Set $\beta_0=1$ and $\beta_1=-0.5$
* Create an array of $x_i$ values from -5 to 5
* Create an array of $\epsilon_i$ values from the standard normal distribution equal in length to the array of $x_i$ values
* Create an array of $y_i$ values
* Plot y against x with either a circle ('o'), triangle ('^'), or square ('s') marker and transparency (alpha) to 0.5
* Add axis lables, a title, and a grid to the plot


```python
# Set betas
beta0 = 1
beta1 = -0.5

# Create x values
x = np.linspace(-5,5,1000)

# Create epsilon values from the standard normal distribution
epsilon = np.random.normal(size=len(x))

# Create y
y = beta0 + beta1*x+epsilon

# Plot
plt.plot(x,y,'s',alpha =0.5)

# Add a title and axis labels
plt.title('Data')
plt.xlabel('x')
plt.ylabel('y')

# Set axis limits
plt.xlim([-5,5])

# Add grid
plt.grid()
```

### Example

Create plots of the functions $f(x) = x$, $g(x) = x^2$, and $h(x) = x^3$ for $x$ between -2 and 2
* Use the optional string format argument to format the lines:
  - $x$: solid blue line
  - $x^2$: dashed green line
  - $x^3$: dash-dot magenta line
* Set the linewidth of each line to 3 points
* Set transparency (alpha) for each line to 0.7
* Set axis labels and title
* Add a legend to lower right with 3 columns
* Add a grid to the plot


```python
# Create an array of x values from -2 to 2
x = np.linspace(-2,2,1000)

# Create y variables
y1 = x
y2 = x**2
y3 = x**3

# Use the plot function to plot the lines
plt.plot(x,y1,'b-',lw=3,label='$x$',alpha=0.7)
plt.plot(x,y2,'g--',lw=3,label='$x^2$',alpha=0.7)
plt.plot(x,y3,'m-.',lw=3,label='$x^3$',alpha=0.7)

# Add a title and axis labels
plt.title('Three functions')
plt.xlabel('x')
plt.ylabel('y')

# Make legend
plt.legend(loc='lower right',ncol=3)

# Add grid
plt.grid()
```

## Figures, Axes, and Subplots

Often we want to create plots with multiple axes or we want to modify the size and shape of the plot areas. To be able to do these things, we need to explicity create a figure and then create axes within the figure. The best way to see how this works is by example.


### Example: A Single Plot with Double Width

The default dimensions of a matplotlib figure are 6 inches by 4 inches. As we saw above, this leaves some whitespace on the right side of the figure in the Notebook. Suppose we want to remove that by making the plot area twice as wide.

Plot the sine function on -6 to 6 using a figure with dimensions 12 inches by 4 inches


```python
# Create an array of x values from -6 to 6
x = np.linspace(-6,6,1000)

# Create y variables
y = np.sin(x)

# Create a new figure that is twice as wide as the default
fig = plt.figure(figsize=(12,4))

# Create axis within the figure
ax1 = fig.add_subplot(1,1,1)

# Plot
ax1.plot(x,y,lw=3,alpha = 0.6)

# Add grid
ax1.grid()
```

In the previous example the `fig = plt.figure()` function creates a new figure called `fig` and `fig.add_subplot()` puts a new axis on the figure. The command `ax1 = fig.add_subplot(1,1,1)` means divide the figure `fig` into a 1 by 1 grid (first two arguments) and assigns the first component of that grid to the variable `ax1` (third argument).

### Example: Two Plots Stacked

Create a new figure with two axes in a column and plot the sine function on -6 to 6 on the top axis and the cosine function on -6 to 6 on the bottom axis.


```python
# Create an array of x values from -6 to 6
x = np.linspace(-6,6,1000)

# Create y variables
y1 = np.sin(x)
y2 = np.cos(x)

# Create a new figure that is twice as tall as the default
fig = plt.figure(figsize=(6,8))

# Create axis 1 and plot with title and axis labels
ax1 = fig.add_subplot(2,1,1)
ax1.plot(x,y1,lw=3,alpha = 0.6)
ax1.grid()
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('sin')

# Create axis 2 and plot with title and axis labels
ax2 = fig.add_subplot(2,1,2)
ax2.plot(x,y2,lw=3,alpha = 0.6)
ax2.grid()
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('cos')

# Improve the spacing between the plots
fig.tight_layout()
```

### Example: Block of Four Plots

The default dimensions of a matplotlib figure are 6 inches by 4 inches. As we saw above, this leaves some whitespace on the right side of the figure. Suppose we want to remove that by making the plot area twice as wide.

Create a new figure with four axes in a two-by-two grid. Plot the following functions on the interval -2 to 2:
* $y = x$
* $y = x^2$
* $y = x^3$
* $y = x^4$

Set the figure size to 12in. by 8in. Run the command `plt.tight_layout()` to adust the figure's margins after creating your figure, axes, and plots.


```python
# Create data for plot
x = np.linspace(-2,2,1000)
y1 = x
y2 = x**2
y3 = x**3
y4 = x**4

# Create a new figure that is twice as wide and twice as tall as the default
fig = plt.figure(figsize=(12,8))

# Create axis 1 and plot with title
ax1 = fig.add_subplot(2,2,1)
ax1.plot(x,y1,lw=3,alpha = 0.6)
ax1.grid()
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('$x$')

# Create axis 2 and plot with title
ax2 = fig.add_subplot(2,2,2)
ax2.plot(x,y2,lw=3,alpha = 0.6)
ax2.grid()
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('$x^2$')

# Create axis 3 and plot with title
ax3 = fig.add_subplot(2,2,3)
ax3.plot(x,y3,lw=3,alpha = 0.6)
ax3.grid()
ax3.set_xlabel('x')
ax3.set_ylabel('y')
ax3.set_title('$x^3$')

# Create axis 4 and plot with title
ax4 = fig.add_subplot(2,2,4)
ax4.plot(x,y4,lw=3,alpha = 0.6)
ax4.grid()
ax4.set_xlabel('x')
ax4.set_ylabel('y')
ax4.set_title('$x^4$')

# Improve the spacing between the plots
plt.tight_layout()
```

## Exporting Figures to Image Files

Use the `plt.savefig()` function to save figures to images.


```python
# Create data to plot sin(x)/x on [-20,20]
x = np.linspace(-20,20,1000)
y = np.sin(x)/x

# Plot y against x
plt.plot(x,y)

# Save figure as 'fig_econ126_class04_sine_over_x.png' at 120 DPI resolution
plt.savefig('fig_econ126_class04_sine_over_x.png',dpi=120)
```

In the previous example, the image is saved as a PNG file with 120 dots per inch. This resolution is high enough to look good even when projected on a large screen. The image format is inferred by the extension on the filename.

02f8439767d0ea9e500c7307b658acf6ba4f8aea
ipynb
Jupyter Notebook
Lecture Notebooks/Econ126_Class_04.ipynb
letsgoexploring/econ126
05f50d2392dd1c7c38b14950cb8d7eff7ff775ee
MIT
2020-12-12T16:28:44.000Z
2021-02-24T12:11:04.000Z
Lecture Notebooks/Econ126_Class_04.ipynb
letsgoexploring/econ126
05f50d2392dd1c7c38b14950cb8d7eff7ff775ee
MIT
2019-04-29T08:50:41.000Z
2019-04-29T08:51:05.000Z
Lecture Notebooks/Econ126_Class_04.ipynb
letsgoexploring/econ126
05f50d2392dd1c7c38b14950cb8d7eff7ff775ee
MIT
2019-03-08T18:49:19.000Z
2022-03-07T23:27:16.000Z
Qwen/Qwen-72B
1. YES
2. YES