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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38208700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 20:30:52  来源:igfitidea点击:

Matplotlib Plot Lines with Colors Through Colormap

pythonnumpymatplotlibcolormap

提问by Scott

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. The code is akin to this:

我在一个图上绘制多条线,我希望它们穿过颜色图的光谱,而不仅仅是相同的 6 或 7 种颜色。代码类似于:

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. I would like to be able to plot up to ~60 different lines, all with different colors.

使用颜色图“jet”和我从 seaborn 导入的另一个颜色图,我得到了以相同顺序重复的相同 7 种颜色。我希望能够绘制多达 60 条不同的线条,所有线条都具有不同的颜色。

回答by Bart

The Matplotlib colormaps accept an argument (0..1, scalar or array) which you use to get colors from a colormap. For example:

Matplotlib 颜色图接受用于0..1从颜色图中获取颜色的参数(、标量或数组)。例如:

col = pl.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 Ndifferent 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])

enter image description here

在此处输入图片说明

回答by Alex Williams

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, e.g., an image)

  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?)

  1. plt.colorbar()不会以很好的方式工作,因为线图不可映射(与例如图像相比)

  2. 由于 for 循环,大量行可能会很慢(尽管这对于大多数应用程序来说可能不是问题?)

These issues can be addressed by using LineCollection. However, this isn't too user-friendly in my (humble) opinion. There is an open suggestion on GitHubfor adding a multicolor line plot function, similar to the plt.scatter(...)function.

这些问题可以通过使用来解决LineCollection。但是,在我(谦虚)看来,这对用户不太友好。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:

产生:

Example 1

示例 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:

产生:

enter image description here

在此处输入图片说明

Hope this helps!

希望这可以帮助!

回答by Ramon Crehuet

An anternative to Bart's answer, in which you do not specify the color in each call to plt.plotis to define a new color cycle with set_prop_cycle. His example can be translated into the following code (I've also changed the import of matplotlib to the recommended style):

Bart 的答案的一个替代方案,其中您没有在每次调用中指定颜色,plt.plot而是使用 定义一个新的颜色循环set_prop_cycle。他的例子可以翻译成下面的代码(我也把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)

回答by Shital Shah

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)