2013-02-08 101 views
46

我试图做一个离散彩条的散点图中matplotlibMatplotlib离散彩条

我有我的X,Y数据和每一个点,我想了一个独特的颜色来表示的整型变量的值,例如

plt.scatter(x, y, c=tag) 

典型地为标签将是一个整数范围从0-20,但确切范围可以改变

到目前为止我刚使用默认设置,例如

plt.colorbar() 

它给出了连续范围的颜色。理想情况下,我想要一组n个不连续的颜色(本例中n = 20)。更好的办法是得到一个0的标签值产生一个灰色的颜色,1-20是丰富多彩的。

我已经发现了一些“菜谱”剧本,但他们都非常复杂,我不认为他们是要解决一个看似简单的问题的正确方法

+1

确实[此](http://matplotlib.org/examples/api/colorbar_only.html)或[此] (http://www.scipy.org/Cookbook/Matplotlib/ColormapTransformations)的帮助? – 2013-02-08 16:40:35

+0

感谢您的链接,但第二个例子是我的意思是极其复杂的手段来执行一个(看似)琐碎的任务 - 第一个链接是有用的 – bph 2013-02-08 17:13:16

回答

58

通过使用BoundaryNorm作为散点图的标准化程序,您可以非常容易地创建自定义离散色条。这个古怪的位(在我的方法中)使0显示为灰色。

对于图像我经常使用cmap.set_bad()并将我的数据转换为numpy蒙版数组。这会让0灰变得容易得多,但是我不能让它与分散或自定义的cmap一起工作。

作为一种替代方案,您可以从头开始创建自己的cmap,或者读出现有的cmap并覆盖一些特定的条目。

# setup the plot 
fig, ax = plt.subplots(1,1, figsize=(6,6)) 

# define the data 
x = np.random.rand(20) 
y = np.random.rand(20) 
tag = np.random.randint(0,20,20) 
tag[10:12] = 0 # make sure there are some 0 values to showup as grey 

# define the colormap 
cmap = plt.cm.jet 
# extract all colors from the .jet map 
cmaplist = [cmap(i) for i in range(cmap.N)] 
# force the first color entry to be grey 
cmaplist[0] = (.5,.5,.5,1.0) 
# create the new map 
cmap = cmap.from_list('Custom cmap', cmaplist, cmap.N) 

# define the bins and normalize 
bounds = np.linspace(0,20,21) 
norm = mpl.colors.BoundaryNorm(bounds, cmap.N) 

# make the scatter 
scat = ax.scatter(x,y,c=tag,s=np.random.randint(100,500,20),cmap=cmap, norm=norm) 

# create a second axes for the colorbar 
ax2 = fig.add_axes([0.95, 0.1, 0.03, 0.8]) 
cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm, spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i') 

ax.set_title('Well defined discrete colors') 
ax2.set_ylabel('Very custom cbar [-]', size=12) 

enter image description here

我个人认为有20点不同的颜色它有点难以阅读的具体价值,但多数民众赞成由你,当然。

+3

伟大的答案 - 我认为这将花费我很长的时间从网上找到文件,非常感谢 – bph 2013-02-08 19:55:44

+0

我不确定这是否被允许,但你能看看我的问题[这里](http ://stackoverflow.com/questions/32766062/how-to-determine-the-colours-when-using-matplotlib-pyplot-imshow)? – Esoemah 2015-09-24 19:33:26

38

你可以按照这个example

#!/usr/bin/env python 
""" 
Use a pcolor or imshow with a custom colormap to make a contour plot. 

Since this example was initially written, a proper contour routine was 
added to matplotlib - see contour_demo.py and 
http://matplotlib.sf.net/matplotlib.pylab.html#-contour. 
""" 

from pylab import * 


delta = 0.01 
x = arange(-3.0, 3.0, delta) 
y = arange(-3.0, 3.0, delta) 
X,Y = meshgrid(x, y) 
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) 
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1) 
Z = Z2 - Z1 # difference of Gaussians 

cmap = cm.get_cmap('PiYG', 11) # 11 discrete colors 

im = imshow(Z, cmap=cmap, interpolation='bilinear', 
      vmax=abs(Z).max(), vmin=-abs(Z).max()) 
axis('off') 
colorbar() 

show() 

这产生以下图片:

poormans_contour

+6

cmap = cm.get_cmap('jet',20)then scatter(x,y,c = tags,cmap = cmap)让我有一部分 - 它很难找到matplotlib – bph 2013-02-08 17:19:02

0

我想你想看看colors.ListedColormap来生成你的色彩地图,或者如果你只需要一个静态的色彩地图我一直在an app可能会有所帮助。

+0

的有用文档,看起来很酷,可能是为了我的需要矫枉过正 - 你能否提出一种将灰度值标记到现有色彩映射上的方法?所以0值呈灰色,其他值则以颜色出现? – bph 2013-02-08 17:58:47

+0

@Hiett根据你的y值生成一个RGB数组color_list,并将其传递给ListedColormap?你可以用color_list [y == value_to_tag] = gray_color标记一个值。 – ChrisC 2013-02-08 18:50:38

23

要设置高于或低于色彩图范围的值,您需要使用色彩映射的set_overset_under方法。如果您想标记某个特定值,请将其掩蔽(即创建一个蒙版阵列),然后使用set_bad方法。 (看一看为基本颜色表类的文档:http://matplotlib.org/api/colors_api.html#matplotlib.colors.Colormap

这听起来像你想是这样的:

import matplotlib.pyplot as plt 
import numpy as np 

# Generate some data 
x, y, z = np.random.random((3, 30)) 
z = z * 20 + 0.1 

# Set some values in z to 0... 
z[:5] = 0 

cmap = plt.get_cmap('jet', 20) 
cmap.set_under('gray') 

fig, ax = plt.subplots() 
cax = ax.scatter(x, y, c=z, s=100, cmap=cmap, vmin=0.1, vmax=z.max()) 
fig.colorbar(cax, extend='min') 

plt.show() 

enter image description here

+0

多数民众赞成在这真的很好 - 我尝试使用set_under,但没有包括vmin,所以我不认为它在做任何事情 – bph 2013-02-08 19:59:03

19

以上答案是好的,但他们不”在颜色条上放置适当的刻度线。我喜欢在颜色中间有滴答,以便数字 - >颜色映射更清晰。可以通过改变呼叫matshow的限制解决这个问题:

import matplotlib.pyplot as plt 
import numpy as np 

def discrete_matshow(data): 
    #get discrete colormap 
    cmap = plt.get_cmap('RdBu', np.max(data)-np.min(data)+1) 
    # set limits .5 outside true range 
    mat = plt.matshow(data,cmap=cmap,vmin = np.min(data)-.5, vmax = np.max(data)+.5) 
    #tell the colorbar to tick at integers 
    cax = plt.colorbar(mat, ticks=np.arange(np.min(data),np.max(data)+1)) 

#generate data 
a=np.random.randint(1, 9, size=(10, 10)) 
discrete_matshow(a) 

example of discrete colorbar

+0

我同意在相应的颜色中间放置勾是非常有用的,当查看离散数据。你的第二种方法是正确的。但是,一般来说,您的第一个方法是_wrong_:您正在用与其在颜色条上的位置不一致的值标记刻度。 'set_ticklabels(...)'只能用来控制标签格式(例如十进制数等)。如果数据确实是离散的,你可能不会注意到任何问题。如果系统中有噪音(例如2 - > 1.9),则此不一致的标签将导致误导和不正确的颜色条。 – 2015-10-31 01:04:00

+0

E.我认为你是对的,改变极限是优越的解决方案,所以我删除了另一个 - 虽然都不能很好地处理“噪音”。处理连续数据需要进行一些调整。 – 2015-11-14 05:39:11