Python matplotlib的平滑插值三级或四级色阶(例如r、g、b三角形)?

Python matplotlib的平滑插值三级或四级色阶(例如r、g、b三角形)?,python,matplotlib,colors,color-space,Python,Matplotlib,Colors,Color Space,假设我要为matplotlib绘图中的点创建颜色方案,每个点都有一定比例的属性a、B和C(每个属性可以取0到1的值)。一种简单的方法是使用,这样点的红色值由A给出,绿色值由B给出,蓝色值由C给出 然而,似乎另一个三角形可以提供更多的“动态范围”,即更容易看到每个点在三角形中的位置。但是,我不知道如何对特定三角形进行编码(即给定A,B和C,返回A(r,g,B)元组)。它还有一个额外的问题,就是中间有白色,在白色背景下看起来不太好 我的问题:对于这样的问题,什么样的三角形色标比较好?这种东西叫什么,

假设我要为matplotlib绘图中的点创建颜色方案,每个点都有一定比例的属性
a
B
C
(每个属性可以取0到1的值)。一种简单的方法是使用,这样点的红色值由
A
给出,绿色值由
B
给出,蓝色值由
C
给出

然而,似乎另一个三角形可以提供更多的“动态范围”,即更容易看到每个点在三角形中的位置。但是,我不知道如何对特定三角形进行编码(即给定
A
B
C
,返回A
(r,g,B)
元组)。它还有一个额外的问题,就是中间有白色,在白色背景下看起来不太好

我的问题:对于这样的问题,什么样的三角形色标比较好?这种东西叫什么,因为我发现很难找到

此外,如果我们想将其扩展到四个属性,
A
B
C
D
,并有一个“彩色方块”,那么四个角的颜色应该是什么,您将如何编写一个函数,从
A
B
C
D
开始,并返回
(r,g,b)
tuple

理想情况下,像这样的配色方案(a)到处都有独特的颜色,(b)没有白色,(c)理想情况下有很高的变化率,以便通过观察更容易看到颜色比例中的位置。更好的方案是安全的色盲方案,但在这种情况下,这可能要求太多

非常感谢您的建议。我的最终目标是用这些配色方案中的一种来制作类似but的产品。谢谢


编辑:添加重要的约束条件
A+B+C=1
,使这在技术上成为可能。举个例子,假设我想提出一个配色方案,使一个独特的颜色映射到A中的特定构图。“明显”的情况是使用RGB三角形,但有更好的解决方案吗?我该如何用Python编写它?

玩类似的游戏,看看如何表示您自己的数据:

import matplotlib.pyplot as plt
from numpy import random

count = 300
space = random.random((count,2))
hue = random.uniform(0,1,(count,3))

def to_rgb(triplet):
    '''convert a triplet of values in the range [0,1]
    to a RGB triplet of values in the range [0, 255] (integers);
    blue is kept to a smaller range so the RGB never turns white.'''

    red = triplet[0]
    green = 1-triplet[1]
    blue = triplet[2]*0.75

    return [red, green, blue]


plt.scatter(space[:,0], space[:,1], c=map(to_rgb, hue), s=60)
plt.show()

你可以利用ColorBrewer关于我们如何解释单色、发散或任何颜色方案的讨论,来找出你想要如何表示三个“颜色”变量中的每一个。(组合表示其中三个变量比较困难。即使是最常见的色盲也很难做到。)

好的,我已经试过了。它不是完美的,有点像黑客,所以改进/建议非常受欢迎。我很乐意接受更好的答案(特别是对
abc\u to\u rgb
的改进,以消除错误,提高动态范围,或者只是为色盲提供更好的配色方案)。我在考虑可能使用的是等效的四元颜色方案(方形图例)。此外,这是我第一次使用重心坐标,因此我对图例的绘制可能并不理想(例如,更好的图例可能不会从边缘“出血”,或者需要太多点)

我们的传奇故事如下:


然后,
abc\u to\u rgb
可以用来为散点图或线图中的给定点获得合适的颜色…

简而言之,你要问的是不同的“颜色空间”。先来看看这里:这些三角形中的任何一个的问题都是它们没有考虑到所有的可能性。事实上,我认为你不能在这样的三角形中表示所有的可能性。要么你忽略a=1,B=1,C=1或a=0,B=0,C=0的情况。你需要一个3D绘图来显示所有的颜色,或者可能是一个真正的三角形复杂的二维。不要担心RGB是三维的:这大概是你想要做的,在页面上放尽可能多的不同信息。当你试图打印颜色空间时,这是一个问题,但当你使用它时就不是了。有一些很好的讨论我们如何解释不同的颜色贴图。真的,我们不能一般地用c选择一个最好的颜色贴图,而不知道你的数据是什么,什么特征需要最明显。@Matthew,我不是说你不能使用特定的贴图,只是你显示的三角形不能说明全部情况。如果你想避免颜色空间中的白色,你可以将a、B和C乘以.75,这样你就不会得到白色n当它们都是1时,那么你的函数只会返回(.75*A、.75*B、.75*C)。谢谢你的回复,但这不是我想要的,我已经发布了一个替代答案。很好,很清楚。错误搜索:为什么AB边界外的边与内部的颜色不太匹配?我不能准确地告诉你,但是任何点
A+B+C>1
都是有效的,它只是位于三角形之外,函数
abc\u to\rgb
没有检查
A
B
C
上的任何约束。但是,我确实将所有点限制在三角形内,但在我的计算机上matplotlib的“像素”标记显示为正方形,这意味着它们会在三角形边缘外流血。因此我不确定错误的确切位置。此外,这这个问题为我提出了另一个问题:如何为重心坐标生成“统一”网格(即
(a,b,c)
元组列表,其中
a+b+c=1
)?
import matplotlib.pyplot as plt
import numpy as np
import math

def abc_to_rgb(A=0.0,B=0.0,C=0.0):
    ''' Map values A, B, C (all in domain [0,1]) to
    suitable red, green, blue values.'''
    return (min(B+C,1.0),min(A+C,1.0),min(A+B,1.0))

def plot_legend():
    ''' Plots a legend for the colour scheme
    given by abc_to_rgb. Includes some code adapted
    from http://stackoverflow.com/a/6076050/637562'''

    # Basis vectors for triangle
    basis = np.array([[0.0, 1.0], [-1.5/np.sqrt(3), -0.5],[1.5/np.sqrt(3), -0.5]])

    fig = plt.figure()
    ax = fig.add_subplot(111,aspect='equal')

    # Plot points
    a, b, c = np.mgrid[0.0:1.0:50j, 0.0:1.0:50j, 0.0:1.0:50j]
    a, b, c = a.flatten(), b.flatten(), c.flatten()

    abc = np.dstack((a,b,c))[0]
    #abc = filter(lambda x: x[0]+x[1]+x[2]==1, abc) # remove points outside triangle
    abc = map(lambda x: x/sum(x), abc) # or just make sure points lie inside triangle ...

    data = np.dot(abc, basis)
    colours = [abc_to_rgb(A=point[0],B=point[1],C=point[2]) for point in abc]

    ax.scatter(data[:,0], data[:,1],marker=',',edgecolors='none',facecolors=colours)

    # Plot triangle
    ax.plot([basis[_,0] for _ in range(3) + [0,]],[basis[_,1] for _ in range(3) + [0,]],**{'color':'black','linewidth':3})

    # Plot labels at vertices
    offset = 0.25
    fontsize = 32
    ax.text(basis[0,0]*(1+offset), basis[0,1]*(1+offset), '$A$', horizontalalignment='center',
            verticalalignment='center', fontsize=fontsize)
    ax.text(basis[1,0]*(1+offset), basis[1,1]*(1+offset), '$B$', horizontalalignment='center',
            verticalalignment='center', fontsize=fontsize)
    ax.text(basis[2,0]*(1+offset), basis[2,1]*(1+offset), '$C$', horizontalalignment='center',
            verticalalignment='center', fontsize=fontsize)    

    ax.set_frame_on(False)
    ax.set_xticks(())
    ax.set_yticks(())

    plt.show()