как добавить цвета в легенду Axes3D.scatter?

Я хотел бы добавить цвета к своим меткам в легенде 3D-графика, но это не работает, когда я пытался с помощью аналогичного метода добавить цвета к обычному plt.plot.

fig = plt.figure(figsize=(10, 8))
ax = Axes3D(fig)
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w', 'tab:blue', 'tab:orange', 
'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', 'tab:olive', 'tab:cyan', 'yellow', 'tomato']

ax.scatter(xs=xs_valence, ys=ys_arousal, zs=zs_dominance, zdir='z', s=len(xs_valence), c=colors, label=labels_df_labels)
ax.legend()
plt.grid(b=True)
plt.show()

Ожидаемый результат должен содержать цвета в легенде для каждой метки.

3D-график

Что я пробовал:

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

scatter = ax.scatter(xs=xs_valence, ys=ys_arousal, zs=zs_dominance, zdir='z', s=len(xs_valence), cmap='Spectral')

X_cmap = .7
kw = dict(prop='colors', num=len(xs_valence), color=scatter.cmap(X_cmap), fmt='{x}', func=lambda s: [s for s in labels_df_labels])

legend1 = ax.legend(*scatter.legend_elements(**kw), loc='upper left', title='Labels')

ax.add_artist(legend1)
plt.show()

Также:

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

for idx, row in df_labels.iterrows():
    color = row['colors']
    label = row['Labels']
    xs_valence, ys_arousal, zs_dominance = row['Valence'], row['Arousal'], row['Dominance']
    
    ax.plot(xs=xs_valence,
            ys=ys_arousal, 
            zs=zs_dominance, 
            zdir='z',
            s=18, 
            label=label, 
            color=color)

plt.legend(loc='upper left', numpoints=1, ncol=3, fontsize=8, bbox_to_anchor=(0, 0))
plt.show()

TypeError                                 Traceback (most recent call last)
<ipython-input-139-4e34b382128f> in <module>()
     13             s=18,
     14             label=label,
---> 15             color=color)
     16 
     17 plt.legend(loc='upper left', numpoints=1, ncol=3, fontsize=8, bbox_to_anchor=(0, 0))

/usr/local/lib/python3.6/dist-packages/mpl_toolkits/mplot3d/axes3d.py in plot(self, xs, ys, zdir, *args, **kwargs)
   1419 
   1420         # Match length
-> 1421         zs = np.broadcast_to(zs, len(xs))
   1422 
   1423         lines = super().plot(xs, ys, *args, **kwargs)

TypeError: object of type 'float' has no len()

person Y4RD13    schedule 13.02.2021    source источник
comment
Чтобы добавить цвет к каждому из них, вам нужно указать цвет в процессе цикла. См. здесь для более подробной информации.   -  person r-beginners    schedule 14.02.2021
comment
@r-beginners, пожалуйста, проверьте, что я пробовал, используя цикл для указания только цветов, вы получите метки с названиями цветов.   -  person Y4RD13    schedule 14.02.2021
comment
Действительно ли данные хранятся в pandas df вместо списков? Если нет, заархивируйте все списки в цикле for.   -  person Mr. T    schedule 14.02.2021
comment
@Mr.T да, это так   -  person Y4RD13    schedule 14.02.2021


Ответы (1)


Я не думаю, что имеет значение, что данные хранятся в кадре данных pandas. В 2D вы можете преобразовать свои данные и использовать pandas оболочка графика, которая пытается угадать множество параметров matlotlib (включая метку ряда данных). Однако это трехмерный сюжет, который имхо не поддерживается графикой панд. Итак, вернемся к старому zip-подходу:

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

#simulate your data
np.random.seed(123)
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w', 'tab:blue', 'tab:orange', 'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', 'tab:olive', 'tab:cyan', 'yellow', 'tomato']
df = pd.DataFrame({"Valence": np.random.random(len(colors)), 
                   "Arousal": np.random.random(len(colors)), 
                   "Dominance": np.random.random(len(colors)),
                   "colors": colors,
                   "Labels": [f"{i}: {c}" for i, c in enumerate(colors)]
                   })

fig = plt.figure(figsize=(10, 8))
ax = Axes3D(fig)
 
for x, y, z, c, l in zip(df.Valence, df.Arousal, df.Dominance, df.colors, df.Labels):
    ax.scatter(xs=x, ys=y, zs=z, s=40, c=c, label=l)

ax.legend(ncol=3)
plt.grid(b=True)
plt.show()

введите здесь описание изображения

person Mr. T    schedule 14.02.2021
comment
Я неправильно понял ответ, это правильно :) - person Y4RD13; 17.02.2021