2014-07-11 22 views
13

Tworzę kilka wykresów punktowych i chcę ustawić rozmiar punktów w legendzie na stałą, równą wartość.Ustawianie stałego rozmiaru dla punktów w legendzie

Teraz mam to:

import matplotlib.pyplot as plt 
import numpy as np 

def rand_data(): 
    return np.random.uniform(low=0., high=1., size=(100,)) 

# Generate data. 
x1, y1 = [rand_data() for i in range(2)] 
x2, y2 = [rand_data() for i in range(2)] 


plt.figure() 
plt.scatter(x1, y1, marker='o', label='first', s=20., c='b') 
plt.scatter(x2, y2, marker='o', label='second', s=35., c='r') 
# Plot legend. 
plt.legend(loc="lower left", markerscale=2., scatterpoints=1, fontsize=10) 
plt.show() 

która produkuje to:

enter image description here

Rozmiary punktów w legendzie są skalowane, ale nie takie same. Jak mogę naprawić rozmiary punktów w legendzie do równej wartości bez wpływu na rozmiary na wykresie scatter?

Odpowiedz

26

Zajrzałem do kodu źródłowego matplotlib. Zła wiadomość jest taka, że ​​nie wydaje się, aby istniał jakikolwiek prosty sposób ustawiania równych wymiarów punktów w legendzie. Jest to szczególnie trudne w przypadku wykresów rozproszonych (nieprawidłowo: patrz aktualizacja poniżej:). Istnieją zasadniczo dwie możliwości:

  1. zmienić kod
  2. maplotlib Dodaj transformacji do PathCollection obiektów reprezentujących kropki na obrazie. Transformacja (skalowanie) musi uwzględniać pierwotny rozmiar.

Żadne z nich nie jest bardzo zabawne, chociaż numer 1 wydaje się łatwiejszy. Szczególnie interesujące są podtypy scatter.

Mam jednak hack który prawdopodobnie robi to, co chcesz:

import matplotlib.pyplot as plt 
import numpy as np 

def rand_data(): 
    return np.random.uniform(low=0., high=1., size=(100,)) 

# Generate data. 
x1, y1 = [rand_data() for i in range(2)] 
x2, y2 = [rand_data() for i in range(2)] 

plt.figure() 
plt.plot(x1, y1, 'o', label='first', markersize=np.sqrt(20.), c='b') 
plt.plot(x2, y2, 'o', label='second', markersize=np.sqrt(35.), c='r') 
# Plot legend. 
lgnd = plt.legend(loc="lower left", numpoints=1, fontsize=10) 

#change the marker size manually for both lines 
lgnd.legendHandles[0]._legmarker.set_markersize(6) 
lgnd.legendHandles[1]._legmarker.set_markersize(6) 
plt.show() 

daje to:

enter image description here

który wydaje się być to, czego chciał.

Zmiany:

  • scatter zmienił się plot, która zmienia skalowanie Marker (stąd sqrt) i uniemożliwia użycie zmienia rozmiar znacznika (jeśli to był zamierzony)
  • wielkość marker zmieniona ręcznie na 6 punktów dla obu znaczników w legendzie

Jak widać, wykorzystuje ukryte właściwości podkreślenia (_legmarker) i jest brzydka. Może się zepsuć przy każdej aktualizacji w matplotlib.

Aktualizacja

Haa, znalazłem go. Lepszym Hack:

import matplotlib.pyplot as plt 
import numpy as np 

def rand_data(): 
    return np.random.uniform(low=0., high=1., size=(100,)) 

# Generate data. 
x1, y1 = [rand_data() for i in range(2)] 
x2, y2 = [rand_data() for i in range(2)] 

plt.figure() 
plt.scatter(x1, y1, marker='o', label='first', s=20., c='b') 
plt.scatter(x2, y2, marker='o', label='second', s=35., c='r') 
# Plot legend. 
lgnd = plt.legend(loc="lower left", scatterpoints=1, fontsize=10) 
lgnd.legendHandles[0]._sizes = [30] 
lgnd.legendHandles[1]._sizes = [30] 
plt.show() 

Teraz _sizes (kolejny podkreślić właściwość) załatwia sprawę. Nie trzeba dotykać źródła, mimo że jest to dość hack. Ale teraz możesz korzystać ze wszystkich ofert scatter.

enter image description here

+0

niebieski ma być mniejsza, ale powinna być prosta naprawić , +1 – Aprillion

+0

Niesamowita odpowiedź DrV! Przepraszam, że nie komentowałem wcześniej, myślałem, że miałem, ale najwyraźniej nigdy nie wysłałem cmmt. – Gabriel

+0

Chciałbym tylko wskazać, że drugi hack już nie działa, przynajmniej dla mnie ('python 3.5',' matplotlib 1.5.1'). Być może zmienili coś w kodzie 'matplotlib'. Ten pierwszy jednak działa, bardzo za to dziękuję. –

4

nie mają wiele sukcesów przy użyciu @ rozwiązania DRV za choć może mój przypadek użycia jest wyjątkowy. Ze względu na gęstość punktów używam najmniejszego rozmiaru znacznika, tj. plt.plot(x, y, '.', ms=1, ...), i chcę, aby symbole legendy były większe.

I po rekomendacji znalazłem na matplotlib forums:

  1. działce dane (nie etykiety)
  2. rekord osie granica (xlimits = plt.xlim())
  3. działki fałszywe dane daleko od rzeczywistych danych z legend- odpowiednie kolory i rozmiary symboli
  4. przywrócić osiach limity (plt.xlim(xlimits))
  5. tworzyć legendę

Oto jak się okazało (w tym kropki są faktycznie mniej ważne, że linie): enter image description here

Nadzieja pomaga to ktoś inny.

4

Podobnie do odpowiedzi, zakładając, że chcesz wszystkie znaczniki o tym samym rozmiarze:

lgnd = plt.legend(loc="lower left", scatterpoints=1, fontsize=10) 
for handle in lgnd.legendHandles: 
    handle.set_sizes([6.0]) 

Z matplotlib 2.0.0

Powiązane problemy