2015-05-14 15 views
27

Dla projektu tworzę kilka wykresów rozproszenia 3D z trzema odpowiednimi rzutami pod nim. Używam różnych kolorów, aby wskazać czwarty parametr. Najpierw wykreślić dane o określonym kolorze, a potem overplot że z innymi danymi o innym kolorze, tak że w końcu kolejność jest taka, że ​​widzę wszystko jak chcę:Kolory zagubione w Matplotlib 3D wykres rozproszenia

This is what I want!

W zaczynało się to dobrze, ale kiedy próbuję zrobić to samo z nieco innymi danymi, kolory się zawiodły. Przedstawione kolory w projekcjach są właściwe, ale niektóre z nich brakuje w działce 3D więc nie pasują już:

Colors messed up :(

Kiedy obrócić wykres 3D w zabawny sposób, kolory są odzyskiwane i widzę je jako oni powinni być:

Funny rotation

jednak nie chcę wykres 3D, który obraca się w zabawny sposób, ponieważ osie się pokręcić i to nie można go tak właściwie odczytać.

Znalazłem jedno rozwiązanie problemu tutaj: plotting 3d scatter in matplotlib. W zasadzie mówi, że powinienem zamienić mój ax.scatter (X, Y) na ax.plot (X, Y, "o"). Kiedy to robię, kolory są pokazywane tak, jak powinny, ale fabuła jest w ten sposób dużo bardziej powikłana i brzydsza. Po prostu chcę to zrobić z działką rozproszoną.

Czy ktoś wie, jak rozwiązać ten problem?

Oto minimalny przykład mojego kodu, tylko dwa kolory:

from mpl_toolkits.mplot3d import art3d 
import numpy as np 
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 
from matplotlib import gridspec 

art3d.zalpha = lambda *args:args[0] 

numcols = 20 
percentage = 50 

def load(Td, pc): 
    T = np.load(str(pc) + 'pctTemperaturesTd=' + str(Td) + '.npy') 
    D = np.load(str(pc) + 'pctDensitiesTd=' + str(Td) + '.npy') 
    CD = np.load(str(pc) + 'pctColDensitiesTd=' + str(Td) + '.npy') 
    return T, D, CD 

def colors(ax): 
    colors = np.zeros((numcols, 4)) 
    cm = plt.get_cmap('gist_rainbow') 
    ax.set_color_cycle([cm(1.*i/numcols) for i in range(numcols)]) 
    for i in range(numcols): 
     color = cm(1.*i/numcols) 
     colors[i,:] = color 
    return colors 

# LOAD DATA 
T10, D10, CD10 = load(10, percentage) 
T200, D200, CD200 = load(200, percentage) 

# 3D PLOT 
fig = plt.figure(1) 
gs = gridspec.GridSpec(4, 4) 

ax = fig.add_subplot(gs[:-1,:-1], projection='3d') 
colours = colors(ax) 

ax.plot(T200/100., np.log10(D200), np.log10(CD200), '*', markersize=10,color=colours[10], mec = colours[10], label='Td = 200', alpha=1) 
ax.plot(T10/100., np.log10(D10), np.log10(CD10), '*', markersize=10,color=colours[0], mec = colours[0], label='Td = 10', alpha=1) 

ax.set_xlabel('\nTg/100', fontsize='x-large') 
ax.set_ylabel('\nlog(nH)', fontsize='x-large') 
ax.set_zlabel('\nlog(colDen)', fontsize='x-large') 
ax.set_xlim(0,5) 
#ax.set_zlim(0,) 
ax.set_ylim(2,6) 

# PROJECTIONS 

# Tg, nH 
ax2 = fig.add_subplot(gs[3,0]) 

ax2.scatter(T200/100., np.log10(D200), marker='*', s=10, color=colours[10], label='Td = 200', alpha=1, edgecolor=colours[10]) 
ax2.scatter(T10/100., np.log10(D10), marker='*', s=10, color=colours[0], label='Td = 10', alpha=1, edgecolor=colours[0]) 

ax2.set_xlabel('Tg/100') 
ax2.set_ylabel('log(nH)') 
ax2.set_xlim(0,6) 

# Tg, colDen 
ax3 = fig.add_subplot(gs[3,1]) 

ax3.scatter(T200/100., np.log10(CD200), marker='*', s=10, color=colours[10], label='Td = 200', alpha=1, edgecolor=colours[10]) 
ax3.scatter(T10/100., np.log10(CD10), marker='*', s=10, color=colours[0], label='Td = 10', alpha=1, edgecolor=colours[0]) 

ax3.set_xlabel('Tg/100') 
ax3.set_ylabel('log(colDen)') 
ax3.set_xlim(0,6) 

# nH, colDen 
ax4 = fig.add_subplot(gs[3,2]) 

ax4.scatter(np.log10(D200), np.log10(CD200), marker='*', s=10, color=colours[10], label='Td = 200', alpha=1, edgecolor=colours[10]) 
ax4.scatter(np.log10(D10), np.log10(CD10), marker='*', s=10, color=colours[0], label='Td = 10', alpha=1, edgecolor=colours[0]) 

ax4.set_xlabel('log(nH)') 
ax4.set_ylabel('log(colDen)') 

# LEGEND 
legend = fig.add_subplot(gs[:,3]) 

text = ['Td = 10', 'Td = 20', 'Td = 30', 'Td = 40', 'Td = 50', 'Td = 60', 'Td = 70', 'Td = 80', 'Td = 90', 'Td = 100', 'Td = 110', 'Td = 120', 'Td = 130', 'Td = 140', 'Td = 150', 'Td = 160', 'Td = 170', 'Td = 180', 'Td = 190', 'Td = 200'] 

array = np.arange(0,2,0.1) 
for i in range(len(array)): 
    legend.scatter(0, i, marker='*', s=100, c=colours[numcols-i-1], edgecolor=colours[numcols-i-1]) 
    legend.text(0.3, i-0.25, text[numcols-i-1]) 
    legend.set_xlim(-0.5, 2.5) 
    legend.set_ylim(0-1, i+1) 

legend.axes.get_xaxis().set_visible(False) 
legend.axes.get_yaxis().set_visible(False) 

gs.tight_layout(fig) 

plt.show() 
+0

Czy możesz udostępnić kod? Czy możesz określić używane struktury danych lub reprezentować kształt danych, których używasz? Co więcej, jak różne są te dwa zestawy danych, których używasz (czy niektóre funkcje są transponowane w jednym zestawie danych w porównaniu do innych? - to wyjaśniałoby wygląd czerwieni podczas obracania wykresów ... ale wciąż jest dziwne)? – kasparg

+0

Zawarłem mój kod. Zbiory danych są po prostu numpy tablicami, druga powinna być podzbiorem pierwszej, więc można powiedzieć, że składa się ona tylko z punktów, które pojawiają się również w pierwszej, ale są one po prostu mniej. Poza tym nic się nie zmienia. Myślę, że to błąd, nie znalazłem sposobu na zmianę kolejności wyświetlania moich danych. Na razie jednak rozwiązałem go, używając "fabuły" zamiast "rozproszenia". – Nikki

+0

Pierwszą rzeczą, na którą patrzę, jest ['zorder'] (http://matplotlib.org/examples/pylab_examples/zorder_demo.html). – kwinkunks

Odpowiedz

1

Zamiast używać ax.plot(x,y, 'o') spróbować ax.plot(x,y,'.') lub ax.plot(x,y,'*'. Model 'o' określa, który z nich ma być używany, a znacznik "o" to duże wypełnienie, dlatego Twoja fabuła wygląda na brzydką.

Powiązane problemy