Установка другого цвета для каждой серии в точечной диаграмме на matplotlib
Предположим, у меня есть три набора данных:
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 комплектов?
Я искал это и мог найти любую ссылку на то, что я прошу.
Edit: уточнение (надеюсь) мой вопрос
Если я вызываю scatter несколько раз, я могу установить только один и тот же цвет на каждом scatter. Кроме того, я знаю, что могу установить цветовой массив вручную, но я уверен, что есть лучший способ сделать это. Мой вопрос тогда: "как я могу автоматически разбросать-построить несколько наборов данных, каждый с другим цветом.
Если это поможет, я могу легко присвоить уникальный номер для каждого набора данных.
6 ответов:
Я не знаю, что вы подразумеваете под "вручную". Вы можете выбрать цветовую карту и сделать цветовой массив достаточно легко:
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
чтобы получить тот, который вы хотите. Например (мне лень набирать десять цветов):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))
[PS: Я действительно ненавижу, что я нужно отбросить 'u' при работе с matplotlib..]
обычный способ построения графиков с точками разных цветов в matplotlib-это передать список цветов в качестве параметра.
например:
import matplotlib.pyplot matplotlib.pyplot.scatter([1,2,3],[4,5,6],color=['red','green','blue'])
когда у вас есть список списков, и вы хотите, чтобы они были окрашены в список. Я думаю, что самый элегантный способ-это то, что предлагает @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])]
легко исправить
если у вас есть только один тип коллекций (например, разброс без полос ошибок), вы также можете изменить цвета после того, как вы построили их, это иногда легче выполнить.
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')
выход дает вам разные цвета, даже если у вас есть много разных диаграмм рассеяния в одном подзаголовке.
этот вопрос немного сложнее до января 2013 года и matplotlib 1.3.1 (Aug 2013), который является самой старой стабильной версией, которую вы можете найти на веб-сайте matpplotlib. Но после этого это довольно тривиально.
потому что нынешний вариант
matplotlib.pylab.scatter
назначение поддержки: массив строки имени цвета, массив номера поплавка с картой цвета, массив РГБ или РГБА.этот ответ посвящен бесконечной страсти @Oxinabox к исправлению версии 2013 года себя в 2015.
у вас есть два варианта использования команды scatter с несколькими цветами в одном вызове.
как
pylab.scatter
поддержка команд используйте массив RGBA, чтобы сделать любой цвет, который вы хотите;еще в начале 2013 года, нет никакого способа сделать это, так как команда поддерживает только один цвет для всей коллекции точек рассеяния. Когда я делал свой проект 10000-line, я придумал общее решение, чтобы обойти его. так что это очень липкий, но я могу сделать это в любой форме, цвет, размер и прозрачный. этот трюк также может быть применен для рисования коллекции путей, коллекции линий....
код также вдохновлен исходным кодом
pyplot.scatter
, Я просто дублировал то, что scatter делает без триггера его рисовать.команда
pyplot.scatter
возвратитьPatchCollection
объект, в файле "matplotlib/collections.py" частная переменная_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()