简体   繁体   English

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

[英]Setting different color for each series in scatter plot on matplotlib

Suppose I have three data sets:假设我有三个数据集:

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

I can scatter plot this:我可以散点图:

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

How can I do this with 10 sets?我怎样才能用 10 组做到这一点?

I searched for this and could find any reference to what I'm asking.我搜索了这个,可以找到我所问的任何参考。

Edit: clarifying (hopefully) my question编辑:澄清(希望)我的问题

If I call scatter multiple times, I can only set the same color on each scatter.如果我多次调用 scatter ,我只能在每个 scatter 上设置相同的颜色。 Also, I know I can set a color array manually but I'm sure there is a better way to do this.另外,我知道我可以手动设置颜色数组,但我确信有更好的方法来做到这一点。 My question is then, "How can I automatically scatter-plot my several data sets, each with a different color.我的问题是,“我如何自动散点图我的几个数据集,每个数据集都有不同的颜色。

If that helps, I can easily assign a unique number to each data set.如果这有帮助,我可以轻松地为每个数据集分配一个唯一编号。

I don't know what you mean by 'manually'.我不知道你所说的“手动”是什么意思。 You can choose a colourmap and make a colour array easily enough:您可以选择颜色图并轻松制作颜色数组:

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 图

Or you can make your own colour cycler using itertools.cycle and specifying the colours you want to loop over, using next to get the one you want.或者你可以使用itertools.cycle制作你自己的颜色循环器并指定你想要循环的颜色,使用next来获得你想要的颜色。 For example, with 3 colours:例如,有 3 种颜色:

import itertools

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

只有 3 种颜色的 Matplotlib 图

Come to think of it, maybe it's cleaner not to use zip with the first one neither:想想看,也许不将zip与第一个一起使用更干净:

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

The normal way to plot plots with points in different colors in matplotlib is to pass a list of colors as a parameter.在 matplotlib 中用不同颜色的点绘制图的正常方法是将颜色列表作为参数传递。

Eg:例如:

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

3色

When you have a list of lists and you want them colored per list.当您有一个列表列表并且您希望它们按列表着色时。 I think the most elegant way is that suggesyted by @DSM, just do a loop making multiple calls to scatter.我认为最优雅的方法是@DSM 建议的方法,只需执行一个循环多次调用即可。

But if for some reason you wanted to do it with just one call, you can make a big list of colors, with a list comprehension and a bit of flooring division:但是,如果出于某种原因,您只想通过一个电话来完成,您可以制作一个大的颜色列表,带有列表理解和一些地板划分:

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

An easy fix一个简单的修复

If you have only one type of collections (eg scatter with no error bars) you can also change the colours after that you have plotted them, this sometimes is easier to perform.如果您只有一种类型的集合(例如没有误差线的散点图),您还可以在绘制它们之后更改颜色,这有时更容易执行。

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)

The only piece of code that you need:您需要的唯一一段代码:

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

The output gives you differnent colors even when you have many different scatter plots in the same subplot.即使您在同一子图中有许多不同的散点图,输出也会为您提供不同的颜色。

在此处输入图片说明

You can always use the plot() function like so:您始终可以像这样使用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()

绘制为散点图但改变颜色

This question is a bit tricky before Jan 2013 and matplotlib 1.3.1 (Aug 2013), which is the oldest stable version you can find on matpplotlib website.这个问题在 2013 年 1 月和 matplotlib 1.3.1(2013 年 8 月)之前有点棘手,这是您可以在 matpplotlib 网站上找到的最旧的稳定版本。 But after that it is quite trivial.但在那之后,它是相当微不足道的。

Because present version of matplotlib.pylab.scatter support assigning: array of colour name string, array of float number with colour map, array of RGB or RGBA.因为当前版本的matplotlib.pylab.scatter支持分配:颜色名称字符串数组,带颜色映射的浮点数数组,RGB 或 RGBA 数组。

this answer is dedicate to @Oxinabox's endless passion for correcting the 2013 version of myself in 2015.这个答案献给@Oxinabox 在 2015 年纠正 2013 版的自己的无尽热情。


you have two option of using scatter command with multiple colour in a single call.您有两个选项可以在一次调用中使用具有多种颜色的 scatter 命令。

  1. as pylab.scatter command support use RGBA array to do whatever colour you want;由于pylab.scatter命令支持使用 RGBA 数组来做任何你想要的颜色;

  2. back in early 2013, there is no way to do so, since the command only support single colour for the whole scatter point collection.早在 2013 年初,就没有办法这样做,因为该命令仅支持整个散点集合的单一颜色。 When I was doing my 10000-line project I figure out a general solution to bypass it.当我在做我的 10000 行项目时,我想出了一个通用的解决方案来绕过它。 so it is very tacky, but I can do it in whatever shape, colour, size and transparent.所以它很俗气,但我可以做任何形状、颜色、大小和透明的。 this trick also could be apply to draw path collection, line collection....这个技巧也可以应用于绘制路径集合,线集合....

the code is also inspired by the source code of pyplot.scatter , I just duplicated what scatter does without trigger it to draw.该代码也受到pyplot.scatter源代码的pyplot.scatter ,我只是复制了 scatter 所做的事情而没有触发它绘制。

the command pyplot.scatter return a PatchCollection Object, in the file "matplotlib/collections.py" a private variable _facecolors in Collection class and a method set_facecolors .命令pyplot.scatter返回一个PatchCollection对象,在文件“matplotlib/collections.py”中, Collection类中的私有变量_facecolors和方法set_facecolors

so whenever you have a scatter points to draw you can do this:所以每当你有一个散点要绘制时,你可以这样做:

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

This works for me:这对我有用:

for each series, use a random rgb colour generator对于每个系列,使用随机 rgb 颜色生成器

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

A MUCH faster solution for large dataset and limited number of colors is the use of Pandas and the groupby function:对于大型数据集和有限数量的颜色,一个更快的解决方案是使用 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()

You can also create a list of colors which includes all the colors you need in your scatter plot and give it as a parameter inside like:您还可以创建一个颜色列表,其中包括散点图中所需的所有颜色,并将其作为参数提供,例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM