在matplotlib上的散点图中为每个系列设置不同的颜色

时间:2012-09-02 14:02:13

标签: python matplotlib scatter-plot

假设我有三个数据集:

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

我可以分散这个情节:

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

我怎么能用10套呢?

我搜索了这个,可以找到我正在问的任何参考。

编辑:澄清(希望)我的问题

如果我多次调用散点图,我只能在每个散点图上设置相同的颜色。另外,我知道我可以手动设置颜色数组,但我确信有更好的方法可以做到这一点。 我的问题是,“我如何自动分散绘制我的几个数据集,每个数据集都有不同的颜色。

如果这有帮助,我可以轻松地为每个数据集分配一个唯一的编号。

8 个答案:

答案 0 :(得分:203)

我不知道'手动'是什么意思。您可以选择颜色图并轻松制作颜色数组:

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 graph with different colors

或者您可以使用itertools.cycle制作自己的颜色循环仪并指定要循环的颜色,使用next获取所需的颜色。例如,有3种颜色:

import itertools

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

Matplotlib graph with only 3 colors

想想看,也许更清楚不使用zip和第一个:{/ p>

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

答案 1 :(得分:36)

在matplotlib中绘制不同颜色点的绘图的常规方法是将颜色列表作为参数传递。

E.g:

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)

3 colors

如果您有一个列表列表,并且希望每个列表都有颜色。 我认为最优雅的方式是由@DSM建议, 只做一个循环,多次调用分散。

但是如果由于某种原因你想只用一个电话就可以做到这一点,你可以制作一个大的颜色列表,列表理解和一些地板部门:

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])]

All plotted

    CREATE TABLE #temp(st_date DATETIME,end_date DATETIME,usr_id INT)
INSERT  #temp VALUES('2007-03-01 00:00:00.000','2015-01-31 00:00:00.000',1),
('2015-02-01 00:00:00.000','2017-04-01 00:00:00.000',1),
('2007-03-01 00:00:00.000','2014-01-31 00:00:00.000',2),
('2007-03-01 00:00:00.000','2015-01-31 00:00:00.000',3),
('2015-03-02 00:00:00.000','2017-04-01 00:00:00.000',3)
DECLARE @st_dt DATETIME = '2015-02-01 00:00:00',@end_dt DATETIME = '2016-10-21 00:00:00'

SELECT * FROM #temp WHERE  @st_dt BETWEEN st_date AND end_date
AND @end_dt BETWEEN st_date AND end_date

DROP TABLE #temp

答案 2 :(得分:15)

轻松修复

如果您只有一种类型的集合(例如,没有误差条的散点图),您也可以在绘制它们之后更改颜色,这有时更容易执行。

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)

您需要的唯一代码:

#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')

即使您在同一个子图中有许多不同的散点图,输出也会为您提供不同的颜色。

enter image description here

答案 3 :(得分:7)

您可以随时使用plot()功能:

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()

plot as scatter but changes colors

答案 4 :(得分:6)

这个问题在2013年1月和matplotlib 1。3。1(2013年8月)之前有点棘手,这是你可以在matpplotlib网站上找到的最古老的稳定版本。但在那之后它是非常微不足道的。

因为当前版本的matplotlib.pylab.scatter支持分配:颜色名称字符串数组,带有颜色映射的浮点数数组,RGB或RGBA数组。

这个答案专注于@ Oxinabox对于在2015年纠正2013年版本的无尽热情。

您可以选择在一次调用中使用具有多种颜色的分散命令。

  1. 由于pylab.scatter命令支持使用RGBA数组来做你想要的任何颜色;

  2. 早在2013年初,就没有办法这样做,因为该命令仅支持整个散点集合的单色。当我在进行10000线项目时,我找到了绕过它的一般解决方案。所以它非常俗气,但我可以做任何形状,颜色,大小和透明。这个技巧也可以应用于绘制路径集合,行集合....

  3. 代码的灵感来自于pyplot.scatter的源代码,我只是重复了散布所做的事情而没有触发它绘制。

    命令pyplot.scatter在文件" matplotlib / collections.py"中返回PatchCollection对象。 _facecolors类中的私有变量Collection和方法set_facecolors

    所以每当你有一个分散点来绘制时你都可以这样做:

    # 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()
    

答案 5 :(得分:1)

这对我有用:

对于每个系列,请使用随机的RGB颜色生成器

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

答案 6 :(得分:1)

使用Pandas和groupby函数可为大型数据集和有限数量的颜色提供更快的解决方案:

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()

答案 7 :(得分:0)

您还可以创建一个颜色列表,其中包括散点图中所需的所有颜色,并将其作为参数提供,例如:

colors = ["red", "blue", "green"]
plt.scatter(X, Y, color = colors)