【问题标题】:Matplotlib Plot Lines with Colors Through ColormapMatplotlib 通过 Colormap 绘制带有颜色的线条
【发布时间】:2021-06-03 02:01:29
【问题描述】:

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

for i in range(20):
     for k in range(100):
          y[k] = i*x[i]
     plt.plot(x,y)
plt.show()

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

【问题讨论】:

标签: python numpy matplotlib colormap


【解决方案1】:

Matplotlib 颜色图接受一个参数(0..1,标量或数组),您可以使用该参数从颜色图中获取颜色。例如:

col = pl.cm.jet([0.25,0.75])    

为您提供(两种)RGBA 颜色的数组:

array([[ 0. , 0.50392157, 1. , 1. ], [ 1. , 0.58169935, 0. , 1. ]])

你可以用它来创建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])

【讨论】:

  • 有人可以指出我在文档中的哪个位置存在这种实现想法吗?我发现通过文档学习在 matplotlib 中使用 cmaps 简直是不可能的。我不断地回到 SO 寻找死胡同的答案。不乏关于如何制作它们的文档,但我没有找到像这个关于如何在情节中实际使用它们的答案。
  • 没有任何选项(据我所知)可以让您“为我的所有plot() 行在这个或那个cmap 中循环着色”,所以您必须使用这个问题的解决方案之一。对于接受颜色图的函数(例如scatterpcolormesh 等),它的文档非常完善。
  • 你知道这是为什么吗?我还找到了关于散点图和其他图的文档,但知道为什么标准 Line2D 图缺少这个吗?
  • 使用Line2D 而不是单独的plot() 调用,Matplotlib 确实可以根据某些指定的cmap 为线条着色。如果您认为它有用,您可以随时在此处发出功能请求:github.com/matplotlib/matplotlib/issues
【解决方案2】:

Bart 的解决方案既好又简单,但有两个缺点。

  1. plt.colorbar() 无法正常工作,因为线图不可映射(例如,与图像相比)

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

这些问题可以通过使用LineCollection 来解决。但是,在我(谦虚的)看来,这对用户来说不太友好。有一个开放的suggestion on GitHub 用于添加多色线图功能,类似于plt.scatter(...) 功能。

这是一个我能够一起破解的工作示例

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

这是一个非常简单的例子:

xs = [[0, 1],
      [0, 1, 2]]
ys = [[0, 0],
      [1, 2, 1]]
c = [0, 1]

lc = multiline(xs, ys, c, cmap='bwr', lw=2)

生产:

还有一些更复杂的东西:

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

生产:

希望这会有所帮助!

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      如果您使用的是 brg、hsv、jet 等连续色板或默认色板,那么您可以这样做:

      color = plt.cm.hsv(r) # r is 0 to 1 inclusive
      

      现在您可以像这样将此颜色值传递给您想要的任何 API:

      line = matplotlib.lines.Line2D(xdata, ydata, color=color)
      

      【讨论】:

      • 这种方法似乎比以前的方法更容易!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 2018-11-16
      • 1970-01-01
      相关资源
      最近更新 更多