<jupyter_start><jupyter_text>Customizing Plot Legends Plot legends give meaning to a visualization, assigning meaning to the various plot elements.We previously saw how to create a simple legend; here we'll take a look at customizing the placement and aesthetics of the legend in Matplotlib.The simplest legend can be created with the ``plt.legend()`` command, which automatically creates a legend for any labeled plot elements:<jupyter_code>import matplotlib.pyplot as plt
plt.style.use('classic')
%matplotlib inline
import numpy as np
x = np.linspace(0, 10, 1000)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), '-b', label='Sine')
ax.plot(x, np.cos(x), '--r', label='Cosine')
ax.axis('equal')
leg = ax.legend();<jupyter_output><empty_output><jupyter_text>But there are many ways we might want to customize such a legend.For example, we can specify the location and turn off the frame:<jupyter_code>ax.legend(loc='upper left', frameon=False)
fig<jupyter_output><empty_output><jupyter_text>We can use the ``ncol`` command to specify the number of columns in the legend:<jupyter_code>ax.legend(frameon=False, loc='lower center', ncol=2)
fig<jupyter_output><empty_output><jupyter_text>We can use a rounded box (``fancybox``) or add a shadow, change the transparency (alpha value) of the frame, or change the padding around the text:<jupyter_code>ax.legend(fancybox=True, framealpha=1, shadow=True, borderpad=1)
fig<jupyter_output><empty_output><jupyter_text>For more information on available legend options, see the ``plt.legend`` docstring.  Choosing Elements for the LegendAs we have already seen, the legend includes all labeled elements by default.If this is not what is desired, we can fine-tune which elements and labels appear in the legend by using the objects returned by plot commands.The ``plt.plot()`` command is able to create multiple lines at once, and returns a list of created line instances.Passing any of these to ``plt.legend()`` will tell it which to identify, along with the labels we'd like to specify:<jupyter_code>y = np.sin(x[:, np.newaxis] + np.pi * np.arange(0, 2, 0.5))
lines = plt.plot(x, y)

# lines is a list of plt.Line2D instances
plt.legend(lines[:2], ['first', 'second']);<jupyter_output><empty_output><jupyter_text>I generally find in practice that it is clearer to use the first method, applying labels to the plot elements you'd like to show on the legend:<jupyter_code>plt.plot(x, y[:, 0], label='first')
plt.plot(x, y[:, 1], label='second')
plt.plot(x, y[:, 2:])
plt.legend(framealpha=1, frameon=True);<jupyter_output><empty_output><jupyter_text>Notice that by default, the legend ignores all elements without a ``label`` attribute set.  Legend for Size of PointsSometimes the legend defaults are not sufficient for the given visualization.For example, perhaps you're be using the size of points to mark certain features of the data, and want to create a legend reflecting this.Here is an example where we'll use the size of points to indicate populations of California cities.We'd like a legend that specifies the scale of the sizes of the points, and we'll accomplish this by plotting some labeled data with no entries:<jupyter_code>import pandas as pd
cities = pd.read_csv('data/california_cities.csv')

# Extract the data we're interested in
lat, lon = cities['latd'], cities['longd']
population, area = cities['population_total'], cities['area_total_km2']

# Scatter the points, using size and color but no label
plt.scatter(lon, lat, label=None,
            c=np.log10(population), cmap='viridis',
            s=area, linewidth=0, alpha=0.5)
plt.axis(aspect='equal')
plt.xlabel('longitude')
plt.ylabel('latitude')
plt.colorbar(label='log$_{10}$(population)')
plt.clim(3, 7)

# Here we create a legend:
# we'll plot empty lists with the desired size and label
for area in [100, 300, 500]:
    plt.scatter([], [], c='k', alpha=0.3, s=area,
                label=str(area) + ' km$^2$')
plt.legend(scatterpoints=1, frameon=False, labelspacing=1, title='City Area')

plt.title('California Cities: Area and Population');<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1107850330154072, 'fraction_numerical': 0.010760577158229395, 'mean_word_length': 5.715927750410509, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, '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': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '230267', 'license': 'MIT', 'n_tokens_mistral': 1319, 'n_tokens_neox': 1237, 'n_words': 480, 'path': '04.06-Customizing-Legends.ipynb', 'repo_name': 'orchardbirds/python-training-2021', 'size': '4089'}