【问题标题】:Setting different color for each series in scatter plot on matplotlib在 matplotlib 上的散点图中为每个系列设置不同的颜色
【发布时间】:2012-09-02 14:02:12
【问题描述】:

假设我有三个数据集:

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

我搜索了这个,可以找到任何关于我所问内容的参考。

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

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

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

【问题讨论】:

  • 这里有什么问题?颜色也可以是数组,但是多次调用 scatter 不能解决什么问题?
  • 如果我多次调用 scatter ,我会得到相同的颜色。我会更新我的问题。

标签: python matplotlib scatter-plot


【解决方案1】:

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

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)

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

import itertools

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

想一想,也许第一个也不使用zip 更干净:

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

【讨论】:

  • +1。不过,在这种情况下,itertools 循环可能不是一个好主意,因为它最终会导致多个数据集具有相同的颜色。
  • @DavidRobinson:如果您指定全部十个,则不会,尽管我同意骑自行车会破坏那里的目的.. :^)
  • 正是——那么这不是一个循环:)
  • @macrocosme:为我工作。将plt.legend(['c{}'.format(i) for i in range(len(ys))], loc=2, bbox_to_anchor=(1.05, 1), borderaxespad=0., fontsize=11) 添加到上面的底部会给我一个带有颜色的图例。
  • 当您想避免某些颜色时,itertools 解决方案非常棒。就我而言,因为背景是黑色的,所以我想避免黑色。
【解决方案2】:

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

例如:

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

当您有一个列表列表并希望它们按列表着色时。 我认为最优雅的方式是@DSM 建议的, 只需执行一个循环,多次调用 scatter 即可。

但是,如果出于某种原因,您只想通过一次调用来完成,您可以制作一个大的颜色列表,其中包含列表理解和一些地板划分:

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

【讨论】:

  • 这对于散点图来说真的很棒是绿色的。
【解决方案3】:

一个简单的解决方法

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

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,感谢您指出,今天下午我已经努力让它在这种情况下也能正常工作,但我找不到任何解决方案,所以我编辑了这个问题并警告了另一个用户。谢谢!
  • 嗨@GM,对不起,我在最终确定解决方案之前发布了一些 cmets,如下所述:stackoverflow.com/q/51444364/7541421
  • 我使用另一种方法为散点图中的每个系列分配颜色。现在它起作用了,不幸的是,当涉及到错误栏时,我无法继续使用您的优雅解决方案,但我仍然非常感谢您的超级有用的帖子!干杯!
【解决方案4】:

您始终可以像这样使用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()

【讨论】:

    【解决方案5】:

    这个问题在 2013 年 1 月和 matplotlib 1.3.1(2013 年 8 月)之前有点棘手,这是您可以在 matpplotlib 网站上找到的最古老的稳定版本。但之后就变得很琐碎了。

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

    这个答案是献给@Oxinabox 对在 2015 年更正 2013 版自己的无尽热情。


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

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

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

    代码也受到pyplot.scatter 的源代码的启发,我只是复制了 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。那么为什么人们想知道怎么做呢?得到它的工作后,我再也懒得再看它了。我的项目是画了很多可视化,上面的代码简化了工作流程。
    【解决方案6】:

    这对我有用:

    对于每个系列,使用随机 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 列表,生成器在 '()' 之间声明
    【解决方案7】:

    对于大型数据集和有限颜色数量的更快解决方案是使用 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()
    

    【讨论】:

      【解决方案8】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-22
        • 2021-01-08
        • 2018-01-14
        • 1970-01-01
        • 2013-12-06
        • 1970-01-01
        • 2020-12-17
        • 1970-01-01
        相关资源
        最近更新 更多