[英]Matplotlib Plot Lines with Colors Through Colormap
I am plotting multiple lines on a single plot and I want them to run through the spectrum of a colormap, not just the same 6 or 7 colors.我在一个图上绘制多条线,我希望它们穿过颜色图的光谱,而不仅仅是相同的 6 或 7 种颜色。 The code is akin to this:代码类似于:
for i in range(20):
for k in range(100):
y[k] = i*x[i]
plt.plot(x,y)
plt.show()
Both with colormap "jet" and another that I imported from seaborn, I get the same 7 colors repeated in the same order.使用颜色图“jet”和我从 seaborn 导入的另一个颜色图,我得到了以相同顺序重复的相同 7 种颜色。 I would like to be able to plot up to ~60 different lines, all with different colors.我希望能够绘制多达 60 条不同的线条,所有线条都具有不同的颜色。
The Matplotlib colormaps accept an argument ( 0..1
, scalar or array) which you use to get colors from a colormap. Matplotlib 颜色图接受一个参数( 0..1
、标量或数组),您可以使用该参数从颜色图中获取颜色。 For example:例如:
col = plt.cm.jet([0.25,0.75])
Gives you an array with (two) RGBA colors:为您提供一个具有(两种)RGBA 颜色的数组:
array([[ 0. , 0.50392157, 1. , 1. ], [ 1. , 0.58169935, 0. , 1. ]])数组([[ 0. , 0.50392157, 1. , 1. ], [ 1. , 0.58169935, 0. , 1. ]])
You can use that to create N
different colors:您可以使用它来创建N
种不同的颜色:
import numpy as np
import matplotlib.pylab as pl
x = np.linspace(0, 2*np.pi, 64)
y = np.cos(x)
pl.figure()
pl.plot(x,y)
n = 20
colors = pl.cm.jet(np.linspace(0,1,n))
for i in range(n):
pl.plot(x, i*y, color=colors[i])
Bart's solution is nice and simple but has two shortcomings. Bart 的解决方案很好也很简单,但有两个缺点。
plt.colorbar()
won't work in a nice way because the line plots aren't mappable (compared to, eg, an image) plt.colorbar()
不会很好地工作,因为线图不可映射(与例如图像相比)
It can be slow for large numbers of lines due to the for loop (though this is maybe not a problem for most applications?)由于 for 循环,大量行可能会很慢(尽管这对于大多数应用程序来说可能不是问题?)
These issues can be addressed by using LineCollection
.这些问题可以通过使用LineCollection
来解决。 However, this isn't too user-friendly in my (humble) opinion.但是,在我(谦虚)看来,这对用户不太友好。 There is an open suggestion on GitHub for adding a multicolor line plot function, similar to the plt.scatter(...)
function. GitHub 上有一个开放的建议,用于添加多色线图函数,类似于plt.scatter(...)
函数。
Here is a working example I was able to hack together这是一个我能够一起破解的工作示例
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
def multiline(xs, ys, c, ax=None, **kwargs):
"""Plot lines with different colorings
Parameters
----------
xs : iterable container of x coordinates
ys : iterable container of y coordinates
c : iterable container of numbers mapped to colormap
ax (optional): Axes to plot on.
kwargs (optional): passed to LineCollection
Notes:
len(xs) == len(ys) == len(c) is the number of line segments
len(xs[i]) == len(ys[i]) is the number of points for each line (indexed by i)
Returns
-------
lc : LineCollection instance.
"""
# find axes
ax = plt.gca() if ax is None else ax
# create LineCollection
segments = [np.column_stack([x, y]) for x, y in zip(xs, ys)]
lc = LineCollection(segments, **kwargs)
# set coloring of line segments
# Note: I get an error if I pass c as a list here... not sure why.
lc.set_array(np.asarray(c))
# add lines to axes and rescale
# Note: adding a collection doesn't autoscalee xlim/ylim
ax.add_collection(lc)
ax.autoscale()
return lc
Here is a very simple example:这是一个非常简单的例子:
xs = [[0, 1],
[0, 1, 2]]
ys = [[0, 0],
[1, 2, 1]]
c = [0, 1]
lc = multiline(xs, ys, c, cmap='bwr', lw=2)
Produces:产生:
And something a little more sophisticated:还有一些更复杂的东西:
n_lines = 30
x = np.arange(100)
yint = np.arange(0, n_lines*10, 10)
ys = np.array([x + b for b in yint])
xs = np.array([x for i in range(n_lines)]) # could also use np.tile
colors = np.arange(n_lines)
fig, ax = plt.subplots()
lc = multiline(xs, ys, yint, cmap='bwr', lw=2)
axcb = fig.colorbar(lc)
axcb.set_label('Y-intercept')
ax.set_title('Line Collection with mapped colors')
Produces:产生:
Hope this helps!希望这有帮助!
An anternative to Bart's answer, in which you do not specify the color in each call to plt.plot
is to define a new color cycle with set_prop_cycle
.一个anternative巴特的答案,在你不指定在每次调用颜色plt.plot
是定义一个新的色彩周期, set_prop_cycle
。 His example can be translated into the following code (I've also changed the import of matplotlib to the recommended style):他的例子可以翻译成下面的代码(我也把matplotlib的导入改成了推荐的样式):
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 64)
y = np.cos(x)
n = 20
ax = plt.axes()
ax.set_prop_cycle('color',[plt.cm.jet(i) for i in np.linspace(0, 1, n)])
for i in range(n):
plt.plot(x, i*y)
If you are using continuous color pallets like brg, hsv, jet or the default one then you can do like this:如果您使用的是 brg、hsv、jet 或默认的连续颜色托盘,那么您可以这样做:
color = plt.cm.hsv(r) # r is 0 to 1 inclusive
Now you can pass this color value to any API you want like this:现在您可以将此颜色值传递给您想要的任何 API,如下所示:
line = matplotlib.lines.Line2D(xdata, ydata, color=color)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.