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


162

假设我有三个数据集:

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套来做到这一点?

我进行了搜索,可以找到我所要求的任何参考。

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

如果我多次调用散点图,则只能在每个散点图上设置相同的颜色。另外,我知道我可以手动设置颜色阵列,但是我敢肯定有更好的方法可以做到这一点。我的问题是:“如何自动散布我的几个数据集,每个数据集具有不同的颜色。

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


1
这里的问题是什么?颜色也可以是一个数组,但是仅多次调用scatter不能解决什么问题?
seberg 2012年

1
如果我多次调用散点图,则会得到相同的颜色。我将更新我的问题。
Yotam'9

Answers:


268

我不知道“手动”是什么意思。您可以选择一个颜色图并足够容易地创建颜色阵列:

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图形具有不同的颜色

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

import itertools

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

Matplotlib图只有3种颜色

想一想,也许最好不要同时使用zip第一个:

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

1
+1。不过,在这种情况下,使用itertools循环可能不是一个好主意,因为它最终会导致多个具有相同颜色的数据集。
大卫·罗宾逊

1
@DavidRobinson:如果您指定所有十位,则不会,尽管我同意骑自行车会打败那里的目的。.:^)
DSM

恰恰是,这不是一个周期:)
David Robinson

4
@macrocosme:对我有用。将plt.legend(['c{}'.format(i) for i in range(len(ys))], loc=2, bbox_to_anchor=(1.05, 1), borderaxespad=0., fontsize=11)上面的内容添加到底部,使我得到了带有颜色的图例。
DSM 2013年

如果您想避免一些颜色,itertools解决方案非常有用。就我而言,由于背景是黑色,所以我要避免黑色。
Fabrizio

50

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

例如:

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

3种颜色

当您有一个列表列表时,您希望每个列表都带有颜色。我认为最优雅的方法是@DSM建议,只需做一个循环进行多次调用即可分散。

但是,如果由于某种原因您只想打一个电话,就可以制作一个大的颜色列表,并具有列表理解力和一些地板分割:

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)

全部绘制

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

一个简单的解决方法

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

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

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

在此处输入图片说明


很好,但是例如,您如何使用此功能添加具有相同颜色的错误栏?@GM
PEBKAC

1
@PEBKAC,您好,感谢您指出,今天下午我已经尽力使它在这种情况下也能工作,但是我找不到任何解决方案,所以我编辑了问题并警告了其他用户。谢谢!
GM

@GM,您好:很抱歉,我在完成解决方案之前发表了一些评论,在此处进行了描述:stackoverflow.com/q/51444364/7541421
PEBKAC

1
我使用另一种方法为散点图中的每个系列分配颜色。现在它可以工作了,不幸的是,当涉及到错误栏时,我无法继续使用您优雅的解决方案,但我仍然非常感谢您提供的超级有用的帖子!干杯!
PEBKAC

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

散布但改变颜色


6

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

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

此答案表示@Oxinabox对在2015年更正2013年版本的我的无尽热情。


您有两个选择,可以在单个调用中使用具有多种颜色的scatter命令。

  1. 作为pylab.scatter命令支持,请使用RGBA数组执行所需的任何颜色;

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

该代码也受到的源代码的启发pyplot.scatter,我只是复制了散点图,而没有触发它绘制。

该命令pyplot.scatter返回一个PatchCollection对象,在文件“matplotlib / collections.py”私有变量_facecolorsCollection类和方法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()

因此阅读起来有点复杂,2013年我使用python一年了。那么为什么人们想知道该怎么做呢?得到成功后,我再也不用再看了。我的项目是进行大量可视化,使用上述代码,工作流程得以简化。
2015年

1

这对我有用:

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

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

我不知道您的颜色变量是什么,但是使用您的方法可以执行以下操作:plt.scatter(your values to the graph, color= (np.random.random_sample(), np.random.random_sample(), np.random.random_sample()) )。您提到了RGB生成器,并声明了RGB列表,生成器在'()'之间声明
Joel Carneiro

0

对于大型数据集和有限数量的颜色,一种更快的解决方案是使用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()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.