Matplotlib'deki dağılım grafiğinde her seri için farklı renk ayarlama


162

Üç veri setim olduğunu varsayalım:

X = [1,2,3,4]
Y1 = [4,8,12,16]
Y2 = [1,4,9,16]

Bunu çizebilirim:

from matplotlib import pyplot as plt
plt.scatter(X,Y1,color='red')
plt.scatter(X,Y2,color='blue')
plt.show()

Bunu 10 set ile nasıl yapabilirim?

Bunu aradım ve ne istediğime herhangi bir referans bulabildim.

Düzenleme: sorum umuyorum (umarım)

Eğer saçılımı birden çok kez ararsam, her saçılmada sadece aynı rengi ayarlayabilirim. Ayrıca, bir renk dizisini elle ayarlayabileceğimi biliyorum, ancak bunu yapmanın daha iyi bir yolu olduğundan eminim. Benim sorum o zaman "Her biri farklı renkte olan birkaç veri setimi nasıl otomatik olarak dağıtabilirim.

Bu yardımcı olursa, her veri kümesine kolayca benzersiz bir numara atayabilirim.


1
Buradaki soru ne? Renk de bir dizi olabilir, ancak sadece birkaç kez saçılma çağrısı ile neyi çözemezsiniz?
seberg

1
Eğer saçılımı birden çok kez ararsam, aynı renkleri elde ederim. Sorumu güncelleyeceğim.
Yotam

Yanıtlar:


269

'Manüel' ile ne demek istediğini bilmiyorum. Bir renk haritası seçebilir ve bir renk dizisini yeterince kolayca yapabilirsiniz:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]

colors = cm.rainbow(np.linspace(0, 1, len(ys)))
for y, c in zip(ys, colors):
    plt.scatter(x, y, color=c)

Matplotlib grafik farklı renkler ile

Ya da istediğiniz rengi elde itertools.cycleetmek için kullanarak döngü yapmak istediğiniz renkleri kullanarak ve belirleyerek kendi renk döngüleyicinizi yapabilirsiniz next. Örneğin, 3 renkle:

import itertools

colors = itertools.cycle(["r", "b", "g"])
for y in ys:
    plt.scatter(x, y, color=next(colors))

Sadece 3 renkli Matplotlib grafiği

Bir düşünün, belki de ilkiyle zipbirlikte kullanmamak daha temiz :

colors = iter(cm.rainbow(np.linspace(0, 1, len(ys))))
for y in ys:
    plt.scatter(x, y, color=next(colors))

1
+1. Bir itertools döngüsü muhtemelen bu durumda iyi bir fikir değildir, çünkü aynı renge sahip birden fazla veri kümesiyle sonuçlanacaktır.
David Robinson

1
@DavidRobinson: Eğer on amaç belirtmek değil, orada bir tür yenilgi kabul ediyorum rağmen amaç değil ..: ^)
DSM

Kesinlikle- o zaman bir döngü değil :)
David Robinson

4
@macrocosme: benim için çalışıyor. plt.legend(['c{}'.format(i) for i in range(len(ys))], loc=2, bbox_to_anchor=(1.05, 1), borderaxespad=0., fontsize=11)Yukarıdan aşağıya eklemek bana renklerle bir efsane verir.
DSM

bazı renklerden kaçınmak istediğinizde itertools çözümü harika. Benim durumumda arka plan siyah olduğu için siyahtan kaçınmak istiyorum.
Fabrizio

50

Matplotlib'de farklı renklerde noktaları olan grafikleri çizmenin normal yolu, bir renk listesini parametre olarak iletmektir.

Örneğin:

import matplotlib.pyplot
matplotlib.pyplot.scatter([1,2,3],[4,5,6],color=['red','green','blue'])

3 renk

Bir liste listeniz olduğunda ve her liste için renkli olmasını istediğinizde. Bence en zarif yolu @DSM tarafından suggesyted olduğunu, sadece saçılma için birden fazla çağrı yapmak bir döngü yapmak.

Ancak, herhangi bir nedenden ötürü sadece bir çağrı ile yapmak istiyorsanız, liste kavrayışı ve biraz döşeme bölümü ile büyük bir renk listesi yapabilirsiniz:

import matplotlib
import numpy as np

X = [1,2,3,4]
Ys = np.array([[4,8,12,16],
      [1,4,9,16],
      [17, 10, 13, 18],
      [9, 10, 18, 11],
      [4, 15, 17, 6],
      [7, 10, 8, 7],
      [9, 0, 10, 11],
      [14, 1, 15, 5],
      [8, 15, 9, 14],
       [20, 7, 1, 5]])
nCols = len(X)  
nRows = Ys.shape[0]

colors = matplotlib.cm.rainbow(np.linspace(0, 1, len(Ys)))

cs = [colors[i//len(X)] for i in range(len(Ys)*len(X))] #could be done with numpy's repmat
Xs=X*nRows #use list multiplication for repetition
matplotlib.pyplot.scatter(Xs,Ys.flatten(),color=cs)

Tümü çizildi

cs = [array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 ...
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00]),
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00]),
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00]),
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00])]

19

Kolay düzeltme

Yalnızca bir tür koleksiyonunuz varsa (örn. Hata çubukları olmayan dağılım), bunları çizdikten sonra renkleri de değiştirebilirsiniz, bu bazen daha kolaydır.

import matplotlib.pyplot as plt
from random import randint
import numpy as np

#Let's generate some random X, Y data X = [ [frst group],[second group] ...]
X = [ [randint(0,50) for i in range(0,5)] for i in range(0,24)]
Y = [ [randint(0,50) for i in range(0,5)] for i in range(0,24)]
labels = range(1,len(X)+1)

fig = plt.figure()
ax = fig.add_subplot(111)
for x,y,lab in zip(X,Y,labels):
        ax.scatter(x,y,label=lab)

İhtiyacınız olan tek kod parçası:

#Now this is actually the code that you need, an easy fix your colors just cut and paste not you need ax.
colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired  
colorst = [colormap(i) for i in np.linspace(0, 0.9,len(ax.collections))]       
for t,j1 in enumerate(ax.collections):
    j1.set_color(colorst[t])


ax.legend(fontsize='small')

Aynı alt grafikte birçok farklı dağılım grafiğiniz olsa bile çıktı size farklı renkler verir.

resim açıklamasını buraya girin


bu harika, ancak bu işlevle aynı renkteki hata çubuklarını nasıl eklersiniz? @GM
PEBKAC

1
Merhaba @PEBKAC, işaret ettiğiniz için teşekkürler, bu durumda da çalışmasını sağlamak için bu öğleden sonra çok çalıştım, ancak herhangi bir çözüm bulamadım, bu yüzden soruyu düzenledim ve diğer kullanıcıları uyardım. Teşekkürler!
GM

Merhaba @ GM, üzgünüm burada açıklanan çözümü tamamlamadan önce birkaç yorum yayınladım: stackoverflow.com/q/51444364/7541421
PEBKAC

1
Dağılım grafiğinde her serinin renklerini atamak için başka bir yöntem kullandım. Şimdi işe yarıyor, maalesef hata çubuklarına geldiğinde zarif çözümünüze devam edemedim, yine de süper yararlı postanız için gerçekten minnettarım! Şerefe!
PEBKAC

7

plot()İşlevi her zaman şu şekilde kullanabilirsiniz :

import matplotlib.pyplot as plt

import numpy as np

x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]
plt.figure()
for y in ys:
    plt.plot(x, y, 'o')
plt.show()

saçılma olarak çiz, ancak renkleri değiştir


6

Bu soru Ocak 2013 ve matpplotlib web sitesinde bulabileceğiniz en eski kararlı sürüm olan matplotlib 1.3.1 (Ağu 2013) 'den önce biraz zor. Ama bundan sonra oldukça önemsiz.

Çünkü matplotlib.pylab.scatteratamanın mevcut sürümü : renk adı dizisi dizisi, renk eşlemeli kayan sayı dizisi, RGB veya RGBA dizisi.

bu cevap @ Oxinabox'un 2015'te kendimi 2013 versiyonunu düzeltmeye yönelik sonsuz tutkusuna adadı.


tek bir çağrıda birden fazla renk içeren dağılım komutunu kullanmak için iki seçeneğiniz vardır.

  1. pylab.scatterkomut desteği olarak istediğiniz rengi yapmak için RGBA dizisini kullanın;

  2. 2013'ün başlarında bunu yapmanın bir yolu yok, çünkü komut tüm dağılım noktası koleksiyonu için sadece tek bir rengi destekliyor. 10000 hatlı projemi yaparken, atlamak için genel bir çözüm buldum. bu yüzden çok yapışkan, ama bunu şekil, renk, boyut ve şeffaf ne olursa olsun yapabilirim. Bu hile yolu toplama, çizgi toplama çizmek için de geçerli olabilir ....

kod da kaynak kodu esinlenerek pyplot.scatter, ben sadece scatter çizmek için tetiklemeden ne yaptı çoğaltılmış.

Komut pyplot.scatterbir dönüş PatchCollectiondosyası "matplotlib / collections.py" özel değişkeninde, Object _facecolorsiçinde Collectionsınıf ve bir yöntem set_facecolors.

çizmek için bir dağılım puanınız olduğunda bunu yapabilirsiniz:

# rgbaArr is a N*4 array of float numbers you know what I mean
# X is a N*2 array of coordinates
# axx is the axes object that current draw, you get it from
# axx = fig.gca()

# also import these, to recreate the within env of scatter command 
import matplotlib.markers as mmarkers
import matplotlib.transforms as mtransforms
from matplotlib.collections import PatchCollection
import matplotlib.markers as mmarkers
import matplotlib.patches as mpatches


# define this function
# m is a string of scatter marker, it could be 'o', 's' etc..
# s is the size of the point, use 1.0
# dpi, get it from axx.figure.dpi
def addPatch_point(m, s, dpi):
    marker_obj = mmarkers.MarkerStyle(m)
    path = marker_obj.get_path()
    trans = mtransforms.Affine2D().scale(np.sqrt(s*5)*dpi/72.0)
    ptch = mpatches.PathPatch(path, fill = True, transform = trans)
    return ptch

patches = []
# markerArr is an array of maker string, ['o', 's'. 'o'...]
# sizeArr is an array of size float, [1.0, 1.0. 0.5...]

for m, s in zip(markerArr, sizeArr):
    patches.append(addPatch_point(m, s, axx.figure.dpi))

pclt = PatchCollection(
                patches,
                offsets = zip(X[:,0], X[:,1]),
                transOffset = axx.transData)

pclt.set_transform(mtransforms.IdentityTransform())
pclt.set_edgecolors('none') # it's up to you
pclt._facecolors = rgbaArr

# in the end, when you decide to draw
axx.add_collection(pclt)
# and call axx's parent to draw_idle()

bu yüzden okumak biraz karmaşık ve 2013 yılında 1 yıl boyunca python kullandım. Peki neden insanlar bunu nasıl yapacaklarını bilmek ister? Çalıştırdıktan sonra, bir daha bakma zahmetine girmedim. projem çok fazla görselleştirme yapmaktı, yukarıdaki kodla iş akışı kolaylaştırıldı.
Hualin

1

Bu benim için çalışıyor:

her seri için rastgele bir rgb renk üreticisi kullanın

c = color[np.random.random_sample(), np.random.random_sample(), np.random.random_sample()]

Ben senin renk değişkendir bilmiyorum, ama yaklaşımı kullanarak o böyle bir şey yapmak mümkündür: plt.scatter(your values to the graph, color= (np.random.random_sample(), np.random.random_sample(), np.random.random_sample()) ). Bir RGB jeneratöründen bahsettiniz ve bir RGB listesi beyan ettiniz, jeneratörler '()' arasında ilan edildi
Joel Carneiro

0

Büyük veri kümesi ve sınırlı sayıda renk için ÇOK daha hızlı bir çözüm, Pandaların ve grup işlevinin kullanılmasıdır:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time


# a generic set of data with associated colors
nsamples=1000
x=np.random.uniform(0,10,nsamples)
y=np.random.uniform(0,10,nsamples)
colors={0:'r',1:'g',2:'b',3:'k'}
c=[colors[i] for i in np.round(np.random.uniform(0,3,nsamples),0)]

plt.close('all')

# "Fast" Scatter plotting
starttime=time.time()
# 1) make a dataframe
df=pd.DataFrame()
df['x']=x
df['y']=y
df['c']=c
plt.figure()
# 2) group the dataframe by color and loop
for g,b in df.groupby(by='c'):
    plt.scatter(b['x'],b['y'],color=g)
print('Fast execution time:', time.time()-starttime)

# "Slow" Scatter plotting
starttime=time.time()
plt.figure()
# 2) group the dataframe by color and loop
for i in range(len(x)):
    plt.scatter(x[i],y[i],color=c[i])
print('Slow execution time:', time.time()-starttime)

plt.show()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.