简体   繁体   English

Matplotlib 通过颜色图绘制带有颜色的线条

[英]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 的解决方案很好也很简单,但有两个缺点。

  1. plt.colorbar() won't work in a nice way because the line plots aren't mappable (compared to, eg, an image) plt.colorbar()不会很好地工作,因为线图不可映射(与例如图像相比)

  2. 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:产生:

示例 1

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM