【问题标题】:Using Colormaps to set color of line in matplotlib在 matplotlib 中使用 Colormaps 设置线条的颜色
【发布时间】:2012-02-14 10:04:35
【问题描述】:

如何使用颜色图(比如jet)使用运行时提供的标量值设置 matplotlib 中线条的颜色?我在这里尝试了几种不同的方法,我想我很难过。 values[] 是一个存储的标量数组。曲线是一组一维数组,标签是文本字符串数组。每个数组都有相同的长度。

fig = plt.figure()
ax = fig.add_subplot(111)
jet = colors.Colormap('jet')
cNorm  = colors.Normalize(vmin=0, vmax=values[-1])
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet)
lines = []
for idx in range(len(curves)):
    line = curves[idx]
    colorVal = scalarMap.to_rgba(values[idx])
    retLine, = ax.plot(line, color=colorVal)
    #retLine.set_color()
    lines.append(retLine)
ax.legend(lines, labels, loc='upper right')
ax.grid()
plt.show()

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    您收到的错误是由于您如何定义jet。您正在创建名为“jet”的基类Colormap,但这与获取“jet”颜色图的默认定义非常不同。永远不要直接创建这个基类,而应该只实例化子类。

    您在示例中发现的是 Matplotlib 中的错误行为。运行此代码时应该会生成更清晰的错误消息。

    这是您示例的更新版本:

    import matplotlib.pyplot as plt
    import matplotlib.colors as colors
    import matplotlib.cm as cmx
    import numpy as np
    
    # define some random data that emulates your indeded code:
    NCURVES = 10
    np.random.seed(101)
    curves = [np.random.random(20) for i in range(NCURVES)]
    values = range(NCURVES)
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    # replace the next line 
    #jet = colors.Colormap('jet')
    # with
    jet = cm = plt.get_cmap('jet') 
    cNorm  = colors.Normalize(vmin=0, vmax=values[-1])
    scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet)
    print scalarMap.get_clim()
    
    lines = []
    for idx in range(len(curves)):
        line = curves[idx]
        colorVal = scalarMap.to_rgba(values[idx])
        colorText = (
            'color: (%4.2f,%4.2f,%4.2f)'%(colorVal[0],colorVal[1],colorVal[2])
            )
        retLine, = ax.plot(line,
                           color=colorVal,
                           label=colorText)
        lines.append(retLine)
    #added this to get the legend to work
    handles,labels = ax.get_legend_handles_labels()
    ax.legend(handles, labels, loc='upper right')
    ax.grid()
    plt.show()
    

    导致:

    使用ScalarMappable 是对我的相关答案中提出的方法的改进: creating over 20 unique legend colors using matplotlib

    【讨论】:

    • 这个答案不是最小的和直截了当的。代码示例包含很多不必要的混乱,并没有显示出对 matplotlib 的良好理解。应该接受 blahreport 的答案。
    • @Yann 我们可以为“plt.scatter”生成不同的颜色吗?
    • 注意:对于 Python3,print scalarMap.get_clim() 行在print 后面应该有括号而不是空格。不过,建议的编辑队列似乎已满。
    【解决方案2】:

    我认为使用 numpy 的 linspace 和 matplotlib 的 cm-type 对象来包含我认为更简单的方法是有益的。上述解决方案可能适用于旧版本。我使用的是python 3.4.3、matplotlib 1.4.3、numpy 1.9.3,我的解决方案如下。

    import matplotlib.pyplot as plt
    
    from matplotlib import cm
    from numpy import linspace
    
    start = 0.0
    stop = 1.0
    number_of_lines= 1000
    cm_subsection = linspace(start, stop, number_of_lines) 
    
    colors = [ cm.jet(x) for x in cm_subsection ]
    
    for i, color in enumerate(colors):
        plt.axhline(i, color=color)
    
    plt.ylabel('Line Number')
    plt.show()
    

    这会产生 1000 条不同颜色的线条,它们横跨整个 cm.jet 颜色图,如下图所示。如果您运行此脚本,您会发现可以放大各个行。

    现在说我希望我的 1000 种线条颜色只跨越 400 到 600 行之间的绿色部分。我只需将开始和停止值更改为 0.4 和 0.6,这导致只使用 cm.jet 颜色图的 20%在 0.4 和 0.6 之间。

    因此,在一行摘要中,您可以相应地从 matplotlib.cm 颜色图创建 rgba 颜色列表:

    colors = [ cm.jet(x) for x in linspace(start, stop, number_of_lines) ]
    

    在这种情况下,我使用名为 jet 的常用映射,但您可以通过调用找到 matplotlib 版本中可用颜色映射的完整列表:

    >>> from matplotlib import cm
    >>> dir(cm)
    

    【讨论】:

    • 当然 1 是最好的值。如果您想要更大范围的颜色,您只需增加number_of_lines。如果您只想要波段中的一部分颜色,您可以根据需要减少 stop 并增加 start
    • 一个简单的问题:如何在绘图中添加颜色条而不是图例?
    • 这是什么jet() 方法?我在 cm docs 中没有看到它
    【解决方案3】:

    来自matplotlib 的线条样式、标记和定性颜色的组合:

    import itertools
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    N = 8*4+10
    l_styles = ['-','--','-.',':']
    m_styles = ['','.','o','^','*']
    colormap = mpl.cm.Dark2.colors   # Qualitative colormap
    for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, colormap)):
        plt.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i)
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=4);
    

    更新:不仅支持ListedColormap,还支持LinearSegmentedColormap

    import itertools
    import matplotlib.pyplot as plt
    Ncolors = 8
    #colormap = plt.cm.Dark2# ListedColormap
    colormap = plt.cm.viridis# LinearSegmentedColormap
    Ncolors = min(colormap.N,Ncolors)
    mapcolors = [colormap(int(x*colormap.N/Ncolors)) for x in range(Ncolors)]
    N = Ncolors*4+10
    l_styles = ['-','--','-.',':']
    m_styles = ['','.','o','^','*']
    fig,ax = plt.subplots(gridspec_kw=dict(right=0.6))
    for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, mapcolors)):
        ax.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i)
    ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=3,prop={'size': 8})
    

    【讨论】:

    • 如何为“coolwarm”cmap 执行此操作?在这种情况下没有 .colors 属性
    • coolwarmLinearSegmentedColormap 类型,与 ListedColormap 类型相反(例如 Dark2)。我已经更新了我的答案以支持 LinearSegmentedColormap colormaps as viridis
    【解决方案4】:

    你可以按照我从我已删除的帐户中写的那样做(禁止新帖子:(有)。它相当简单且好看。

    我通常使用这 3 个中的第 3 个,我也没有检查 1 和 2 版本。

    from matplotlib.pyplot import cm
    import numpy as np
    
    #variable n should be number of curves to plot (I skipped this earlier thinking that it is obvious when looking at picture - sorry my bad mistake xD): n=len(array_of_curves_to_plot)
    #version 1:
    
    color=cm.rainbow(np.linspace(0,1,n))
    for i,c in zip(range(n),color):
       ax1.plot(x, y,c=c)
    
    #or version 2: - faster and better:
    
    color=iter(cm.rainbow(np.linspace(0,1,n)))
    c=next(color)
    plt.plot(x,y,c=c)
    
    #or version 3:
    
    color=iter(cm.rainbow(np.linspace(0,1,n)))
    for i in range(n):
       c=next(color)
       ax1.plot(x, y,c=c)
    

    示例 3:

    Ship RAO of Roll vs Ikeda damping in function of Roll amplitude A44

    【讨论】:

      猜你喜欢
      • 2022-01-05
      • 1970-01-01
      • 2011-03-23
      • 1970-01-01
      • 2014-03-21
      • 1970-01-01
      • 2011-01-28
      • 2017-06-18
      • 1970-01-01
      相关资源
      最近更新 更多