matplotlib 参数'c'和'cmap'是如何表现的?

jobtbby3  于 2023-05-18  发布在  其他
关注(0)|答案(2)|浏览(257)

对于pyplot.scatter(x,y,s,c....)函数,

matplotlib文档指出:
c:颜色、顺序或颜色的顺序,可选,默认:'B'标记颜色。可能的值:
单一颜色格式字符串。长度为n的颜色规格序列。n个数字的序列,要使用cmap和normMap到颜色。一种二维阵列,其中行为RGB或RGBA。请注意,c不应是单个数字RGB或RGBA序列,因为这与要进行颜色Map的值数组无法区分。如果要为所有点指定相同的RGB或RGBA值,请使用具有单行的二维阵列。

然而,我不明白如何改变数据点的颜色

我有一段代码:

import matplotlib.pyplot as plt
import numpy as np
import sklearn
import sklearn.datasets
import sklearn.linear_model
import matplotlib

%matplotlib inline
matplotlib.rcParams['figure.figsize'] = (13.0, 9.0)

# Generate a dataset and plot it
np.random.seed(0)
X, y = sklearn.datasets.make_moons(200, noise=0.55)
print(y)
plt.scatter(X[:,0], X[:,1], c=y)#, cmap=plt.cm.Spectral)

**如果我愿意,如何更改颜色以假设数据点为黑色和绿色?还是别的什么另外,请解释一下Cmap到底是做什么的。

  • 为什么每次使用plt.cm.Spectral时我的图都是洋红色和蓝色的?*
q7solyqu

q7solyqu1#

基本上有两个选项,关于如何着色散点。

1.外部Map

您可以在外部将值Map到颜色,并将这些颜色的列表/数组提供给scatterc参数。

z = np.array([1,0,1,0,1])
colors = np.array(["black", "green"])
plt.scatter(x,y, c=colors[z])

2.内部Map

除了显式颜色之外,还可以提供值的列表/数组,这些值应该根据归一化和颜色Map表Map到颜色。

  • colormap是一个可调用对象,它接受0.1.之间的浮点值作为输入,并返回RGB颜色。
  • 规范化是一个可调用对象,它接受任何数字作为输入,并根据一些先前设置的限制输出另一个数字。Normalize的通常情况将提供vminvmax之间的值到0.1.之间的范围的线性Map。

从一些数据获得颜色的自然方式因此是将两者链接,

cmap = plt.cm.Spectral
norm = plt.Normalize(vmin=4, vmax=5)
z = np.array([4,4,5,4,5])
plt.scatter(x,y, c = cmap(norm(z)))

这里,4的值将通过归一化Map到0,并且5的值将Map到1,使得色图提供两个最外面的颜色。
如果向c提供了一个数值数组,则此过程在scatter内部发生。
scatter创建PathCollection,它子类ScalarMappableScalarMappable由一个色彩Map表、一个归一化和一个值数组组成。因此,上述内容通过以下方式内化:

plt.scatter(x,y, c=z, norm=norm, cmap=cmap)

如果最小值和最大值数据被用作标准化的限制,则可以省略该参数。

plt.scatter(x,y, c=z, cmap=cmap)

这就是问题中的输出总是紫色和黄色点的原因,与c提供的值无关。
回到将01数组Map到黑色和绿色的要求,现在可以查看colormaps provided by matplotlib并寻找一个包含黑色和绿色的颜色Map。例如nipy_spectral颜色Map

这里黑色位于颜色图的开头,绿色位于中间的某个地方,比如0.5。因此,需要将vmin设置为0,并且将vmax设置为0,使得vmax*0.5 = 1(其中1是要Map到绿色的值),即vmax = 1./0.5 == 2.

import matplotlib.pyplot as plt
import numpy as np
x,y = np.random.rand(2,6)
z = np.array([0,0,1,1,0,1])

plt.scatter(x,y, c = z, 
            norm = plt.Normalize(vmin=0, vmax=2),
            cmap = "nipy_spectral")

plt.show()

由于可能不总是存在具有可用的期望颜色的颜色图,并且由于从现有颜色图获得颜色位置可能不是直接的,所以替代方案是创建专门用于期望目的的新颜色图。
这里我们可以简单地创建一个黑色和绿色两种颜色的颜色Map。

matplotlib.colors.ListedColormap(["black", "green"])

这里我们不需要任何归一化,因为我们只有两个值,因此可以依赖于自动归一化。

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
x,y = np.random.rand(2,6)
z = np.array([0,0,1,1,0,1])

plt.scatter(x,y, c = z, cmap = mcolors.ListedColormap(["black", "green"]))

plt.show()

dgjrabp2

dgjrabp22#

首先,要根据y中的值设置颜色,可以这样做:

color = ['red' if i==0  else 'green' for i in y]
plt.scatter(X[:,0], X[:,1], c=color)

scatter()cmap
ColorMaps用于提供来自浮点值的颜色。参见this documentation for reference on colormaps

对于0到1之间的值,将从这些颜色Map表中选择一种颜色。
例如:

plt.cm.Spectral(0.0)
# (0.6196078431372549, 0.00392156862745098, 0.25882352941176473, 1.0) #<== magenta

plt.cm.Spectral(1.0)
# (0.3686274509803922, 0.30980392156862746, 0.6352941176470588, 1.0) #<== blue

plt.cm.Spectral(1)
# (0.6280661284121491, 0.013302575932333718, 0.26082276047673975, 1.0)

请注意,在上面的代码中,1.0和1的结果是不同的,因为int和floats的处理方式不同,如__call__()文档中所述:
对于浮点数,X应该在[0.0, 1.0]区间内,以返回沿着Colormap线的RGBA值X*100百分比。
对于整数,X应在[0, Colormap.N)区间内,以从索引为X的色彩Map表返回RGBA值 indexed
请看这个答案,以获得关于色彩Map表的更好的解释:

在y中,您有0和1,因此使用上面代码中显示的RGBA值(表示“光谱”色图的两端)。
下面是plt.scatter()中的ccmap参数如何相互作用。

_______________________________________________________________________
|No | type of x, y |  c type  | values in c |       result              |
|___|______________|__________|_____________|___________________________|
|1  |   single     |  scalar  |   numbers   | cmap(0.0), no matter      |
|   |    point     |          |             |  what the value in c      |
|___|______________|__________|_____________|___________________________|
|2  |   array of   |  array   |   numbers   | normalize the values in c,|                
|   |    points    |          |             | cmap(normalized val in c) |
|___|______________|__________|_____________|___________________________|
|3  | scalar or    | scalar or| RGBA Values,|  no use of cmap,          |
|   |  array       |  array   |Color Strings|  use colors from c        |
|___|______________|__________|_____________|___________________________|

现在,一旦最终确定了实际颜色,然后循环x, y中每个点的颜色。如果x,y的大小等于或小于c中颜色的大小,那么你会得到完美的Map,否则会再次使用旧的颜色。
这里有一个例子来说明这一点:

# Case 1 from above table

# All three points get the same color = plt.cm.Spectral(0)
plt.scatter(x=0.0, y=0.2, c=0, cmap=plt.cm.Spectral)
plt.scatter(x=0.0, y=0.3, c=1, cmap=plt.cm.Spectral)
plt.scatter(x=0.0, y=0.4, c=1.0, cmap=plt.cm.Spectral)

# Case 2 from above table

# The values in c are normalized 
# highest value in c gets plt.cm.Spectral(1.0)
# lowest value in c gets plt.cm.Spectral(0.0)
# Others in between as per normalizing
# Size of arrays in x, y, and c must match here, else error is thrown
plt.scatter([0.1, 0.1, 0.1, 0.1, 0.1], [0.2, 0.3, 0.4, 0.5, 0.6], 
            c=[1, 2, 3, 4, 5], cmap=plt.cm.Spectral)

# Case 3 from above table => No use of cmap here,
#  blue is assigned to the point
plt.scatter(x=0.2, y=0.3, c='b')

# You can also provide rgba tuple
plt.scatter(x=0.2, y=0.4, c=plt.cm.Spectral(0.0))

# Since a single point is present, the first color (green) is given
plt.scatter(x=0.2, y=0.5, c=['g', 'r'])

# Same color 'cyan' is assigned to all values
plt.scatter([0.3, 0.3, 0.3, 0.3, 0.3], [0.2, 0.3, 0.4, 0.5, 0.6], 
            c='c')

# Colors are cycled through points
# 4th point will get again first color
plt.scatter([0.4, 0.4, 0.4, 0.4, 0.4], [0.2, 0.3, 0.4, 0.5, 0.6], 
            c=['m', 'y', 'k'])

# Same way for rgba values
# Third point will get first color again
plt.scatter([0.5, 0.5, 0.5, 0.5, 0.5], [0.2, 0.3, 0.4, 0.5, 0.6], 
            c=[plt.cm.Spectral(0.0), plt.cm.Spectral(1.0)])

输出:

浏览代码中的注解和点的位置沿着颜色,以彻底理解。
您也可以在Case 3的代码中将参数c替换为color,结果仍然相同。

相关问题