0

I'm trying to plot a 3D-scatterplot using matplotlib but for some reason the output doesn't show up with the legends. I want the legend to be one of my dataframe columns (category).

fig = plt.figure(figsize=(12,8))
ax = Axes3D(fig)

color_dict = { 'Beauty':'red', 'Kids':'green', 'Food':'blue', 'Jewelry':'yellow')}

names = df['category'].unique()

for s in names:
  sc = ax.scatter(embedding[:,0], embedding[:,1], embedding[:,2], s=40,
  color=[color_dict[i] for i in df_brands['category']], marker='x', label=names[s])

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
ax.legend()
# plt.show()
plt.legend(*sc.legend_elements(), bbox_to_anchor=(1.05, 1), loc=2)

As can be seen in the output below, the legend is showing like all categories are the same color (red) in the top right corner. (I simplify the code to 4 colours, ignore the fact there are more colours in the plot).

enter image description here

Any help would be appreciated. Thanks!

Flika205
  • 532
  • 1
  • 3
  • 18

2 Answers2

0

You need to add arguments to the ax.legend() function call in the form of a list, telling it what do you need the legend to display.

Add a loc="upper right" argument to position the legend to top right.

Something like this:

# importing modules
import numpy as np
import matplotlib.pyplot as plt

# Y-axis values
y1 = [2, 3, 4.5]

# Y-axis values
y2 = [1, 1.5, 5]

# Function to plot
plt.plot(y1)
plt.plot(y2)

# Function add a legend
plt.legend(["blue", "green"], loc ="upper right")

# function to show the plot
plt.show()

Output: Output1

Also, see this page for reference: https://www.geeksforgeeks.org/matplotlib-pyplot-legend-in-python/

So, I would solve your legend problem as:

fig = plt.figure(figsize=(12,8))
ax = Axes3D(fig)

color_dict = { 'Beauty':'red', 'Kids':'green', 'Food':'blue', 'Jewelry':'yellow')}

names = df['category'].unique()

sc = ax.scatter(embedding[:,0], embedding[:,1], embedding[:,2], s=40,
color=[color_dict[i] for i in df_brands['category']], marker='x', label=names)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
ax.legend(['Label1', 'Label2', 'Label3', 'Label4') # 4 Labels for 4 colours
# plt.show()
plt.legend(*sc.legend_elements(), bbox_to_anchor=(1.05, 1), loc=2)

I can't show output of your improved code, since I do not have your dataframe

  • this added only the first label to the plot (`Beauty` in this case) – Flika205 Jun 08 '21 at 17:11
  • Did you add the 3 legends in the form of a list as an argument? Or just 1? Send what did too. – Abhijeet Mankani Jun 10 '21 at 03:19
  • Yes, I did add the list like you posted above, next to the `loc ="upper right"`. I managed to get the legends to shown using a for loop. But now the issue is that the legend shows like all data points are red (the plot show multiple colors). I'll edit my questions so you can see my latest code. – Flika205 Jun 10 '21 at 06:59
0

In the case of scatter plots, the legend information is not automatically summarized, so it is set in a loop. For test data only, we have implemented plotly.

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd

import plotly.express as px
df = px.data.iris()
fig = plt.figure(figsize=(12,8))

ax = fig.add_subplot(111, projection='3d')

color_dict = {'setosa':'red', 'versicolor':'green', 'virginica':'blue'}

names = df['species'].unique()

for s in names:
    embedding = df.loc[df['species'] == s]
    sc = ax.scatter(embedding.iloc[:,0], embedding.iloc[:,1], embedding.iloc[:,2], s=40,
    c=[color_dict[i] for i in embedding['species']], marker='x',  label=s)
    plt.legend(loc=2, bbox_to_anchor=(1.05, 1))
    
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

plt.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32
  • May I ask you kindly to check related [question](https://stackoverflow.com/questions/68895380/automated-legend-creation-for-3d-plot). Thanks in advance – Mario Sep 01 '21 at 18:48