2

Every option I try does not get the legend to show for my plot. Please help. Here's the code and the plot works fine with all my inputs being simple NumPy arrays. When adding the legend function a tiny box appears in the corner so I know that the instruction is running but with nothing in it. I'm using Jupyter Notebook and my other attempts are shown after #. Can anyone find the flaw:

import pandas as pd
import matplotlib.pyplot as plt

ratios = ['Share Price', 'PEG', 'Price to Sales']
final_z_scores = np.transpose(final_z_scores)
print(final_z_scores)

fig = plt.figure(figsize=(6,4))

#plt.plot(ratios, final_z_scores[0], ratios, final_z_scores[1], ratios, final_z_scores[2])
first = plt.plot(ratios, final_z_scores[0])
second = plt.plot(ratios, final_z_scores[1])

#ax.legend((first, second), ('oscillatory', 'damped'), loc='upper right', shadow=True)
ax.legend((first, second), ('label1', 'label2'))
plt.xlabel('Ratio Types')
plt.ylabel('Values')
plt.title('Final Comparisons of Stock Ratios')
plt.legend(loc='upper left')

plt.plot()
plt.show()
William Miller
  • 9,839
  • 3
  • 25
  • 46

5 Answers5

6

Calling plt.legend() without specifying the handles or labels explicitly obeys the description of this call signature outlined here:

The elements to be added to the legend are automatically determined, when you do not pass in any extra arguments.

In this case, the labels are taken from the artist. You can specify them either at artist creation or by calling the set_label() method on the artist:

So in order to have the legend be automatically populated in your example you simply need to assign labels to the different plots:

import pandas as pd
import matplotlib.pyplot as plt

ratios = ['Share Price', 'PEG', 'Price to Sales']
final_z_scores = np.transpose(final_z_scores)

fig = plt.figure(figsize=(6,4))
first = plt.plot(ratios, final_z_scores[0], label='label1')
second = plt.plot(ratios, final_z_scores[1], label='label2')

plt.xlabel('Ratio Types')
plt.ylabel('Values')
plt.title('Final Comparisons of Stock Ratios')
plt.legend(loc='upper left')

# Calling plt.plot() here is unnecessary 
plt.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
William Miller
  • 9,839
  • 3
  • 25
  • 46
0

You can change the way that labels are assigned in the plt.plot() calls:

first = plt.plot(ratios, final_z_scores[0], label='label1')
second = plt.plot(ratios, final_z_scores[1], label='label2')

Then you can modify your legend call to simply be: plt.legend().

Philip Ciunkiewicz
  • 2,652
  • 3
  • 12
  • 24
0

Take into consideration that the legend attribute takes a list as it’s argument. Try something like this:

plt.legend(['first stock name', 'second stock name'])
William Miller
  • 9,839
  • 3
  • 25
  • 46
0

It looks like you are mixing object-oriented (OO) style of plotting with PyPlot style. If you use OO style, you start with defining ax:

fig, ax = plt.subplots()

Whereas for PyPlot style you use plt.plot() directly, without defining ax first

In your code you did not define ax, you use PyPlot style:

first = plt.plot(ratios, final_z_scores[0])
second = plt.plot(ratios, final_z_scores[1])

To solve your problem, keep using PyPlot style:

first = plt.plot(ratios, final_z_scores[0], label='label1')
second = plt.plot(ratios, final_z_scores[1], label='label2')
...
plt.legend()
plt.plot()

Do not use ax.legend((first, second), ('label1', 'label2')) at all - it's an object which you did not define in the first place

A good explanation of the difference between OO and PyPlot style is here: https://matplotlib.org/3.2.0/tutorials/introductory/usage.html#sphx-glr-tutorials-introductory-usage-py

denis_smyslov
  • 741
  • 8
  • 8
0

Replace dataframe.columns.tolist() with a list of your columns. Hope it helps:

ax.legend(dataframe.columns.tolist())


def plot_df(dataframe,x_label:str,y_label:str, title:str="" ):
    """
    requires plt.show() to display graph
    """

    
    
    fig,ax = plt.subplots(figsize=(15, 10))
   
    ax.set_xlabel(x_label)
    ax.set_ylabel(y_label)
    if title:
        ax.set_title(title)

    hourlocator = md.HourLocator(interval = 1)

    # Set the format of the major x-ticks:
    majorFmt = md.DateFormatter('%H:%M')  

    ax.xaxis.set_major_locator(hourlocator)
    ax.xaxis.set_major_formatter(majorFmt)
    ax.plot(dataframe.index,dataframe.values)
    ax.legend(dataframe.columns.tolist())
    fig.autofmt_xdate() #makes 30deg tilt on tick labels
Flair
  • 2,609
  • 1
  • 29
  • 41