在python中复制R/ggplot2颜色

在python中复制R/ggplot2颜色,python,matplotlib,python-ggplot,Python,Matplotlib,Python Ggplot,此链接具有R代码以复制ggplot的颜色: 我尝试过用python复制代码-但结果不正确 import pandas as pd import numpy as np import matplotlib.pyplot as plt import math import colorsys # function to return a list of hex colour strings def colorMaker(n=12, start=15.0/360.0, saturation=1.0,

此链接具有R代码以复制ggplot的颜色:

我尝试过用python复制代码-但结果不正确

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
import colorsys

# function to return a list of hex colour strings
def colorMaker(n=12, start=15.0/360.0, saturation=1.0, valight=0.65) :
    listOfColours = []
    for i in range(n) :
        hue = math.modf(float(i)/float(n) + start)[0]
        #(r,g,b) = colorsys.hsv_to_rgb(hue, saturation, valight)
        (r,g,b) = colorsys.hls_to_rgb(hue, valight, saturation)
        listOfColours.append( '#%02x%02x%02x' % (int(r*255), int(g*255), int(b*255)) )
    return listOfColours

# made up data
x = np.array(range(20))
d = {}
d['y1'] = pd.Series(x, index=x)
d['y2'] = pd.Series(1.5*x + 1, index=x)
d['y3'] = pd.Series(2*x + 2, index=x)
df = pd.DataFrame(d)

# plot example
plt.figure(num=1, figsize=(10,5), dpi=100) # set default image size
colours = colorMaker(n=3)
df.plot(linewidth=2.0, color=colours)
fig = plt.gcf()
fig.savefig('test.png')
结果

您应该检查一个非常整洁的matplotlib扩展。有一个ggplot样式,请参见。 例如(来自链接):

在matplotlib的基础上构建库,以更直接的方式创建美观的情节,已经有了相当多的努力。目前,有几种选择。不幸的是,生态系统严重支离破碎

除了Jakob提到的MPL工具之外,我想指出以下三点:

  • Python-ggplot:;及
  • 海伯恩:
  • prettyplotlib:
如果您已经熟悉R的ggplot2,那么您应该对python ggplot感到非常满意,我衷心鼓励您对此做出贡献。就我个人而言,我认为我永远也不会想到那种绘图API的风格(这是对我自己的批评,而不是ggplot)。最后,我粗略地观察了Seaborn和prettyplotlib,使我相信它们更类似于mpltools,因为它们提供了基于matplotlib的方便函数


从事物的声音来看,熊猫社区至少正在投入更多的精力来培育海洋生物和野生动物。我个人对此感到兴奋。值得一提的是,所有这些努力都是在matplotlib之上构建的,而不是替换matplotlib。我认为大多数人(包括自己在内)都非常感谢MPL开发人员在过去十年中创建的强大而通用的框架。

仔细查看gg代码-看起来我有两个问题。第一个是分母应该是n+1,而不是n。第二个问题是我需要一个色相-色度-亮度转换工具;而不是我一直采用的色调-亮度饱和度方法。不幸的是,我不知道python中有hcl_to_rgb工具;于是写了一个

我的解决方案(如下)解决了这两个问题。在我看来,我认为它复制了ggplot2的颜色

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
import collections

def hcl_to_rgb(hue=0, chroma=0, luma=0) :
    # Notes:
    #   coded from http://en.wikipedia.org/wiki/HSL_and_HSV#From_luma.2Fchroma.2Fhue
    #   with insights from gem.c in MagickCore 6.7.8
    #   http://www.imagemagick.org/api/MagickCore/gem_8c_source.html
    # Assume:
    #   h, c, l all in range 0 .. 1 (cylindrical coordinates)
    # Returns a tuple:
    #   r, g, b all in the range 0 .. 1 (cubic cartesian coordinates)

    # sanity checks
    hue = math.modf(float(hue))[0]
    if hue < 0 or hue >= 1 :
        raise ValueError('hue is a value greater than or equal to 0 and less than 1')
    chroma = float(chroma)
    if chroma < 0 or chroma > 1 :
        raise ValueError('chroma is a value between 0 and 1')
    luma = float(luma)
    if luma < 0 or luma > 1 :
        raise ValueError('luma is a value between 0 and 1')

    # do the conversion
    _h = hue * 6.0
    x = chroma * ( 1 - abs((_h % 2) - 1) )

    c = chroma
    if   0 <= _h and _h < 1 :
        r, g, b = (c, x, 0.0)
    elif 1 <= _h and _h < 2 :
        r, g, b = (x, c, 0.0)
    elif 2 <= _h and _h < 3 :
        r, g, b = (0.0, c, x)
    elif 3 <= _h and _h < 4 :
        r, g, b = (0.0, x, c)
    elif 4 <= _h and _h < 5 :
        r, g, b = (x, 0.0, c)
    elif 5 <= _h and _h <= 6 :
        r, g, b = (c, 0.0, x)
    else :
        r, g, b = (0.0, 0.0, 0.0)

    m = luma - (0.298839*r + 0.586811*g + 0.114350*b)
    z = 1.0
    if m < 0.0 :
        z = luma/(luma-m)
        m = 0.0
    elif m + c > 1.0 :
        z = (1.0-luma)/(m+c-luma)
        m = 1.0 - z * c
    (r, g, b) = (z*r+m, z*g+m, z*b+m)

    # clipping ...
    (r, g, b) = (min(r, 1.0), min(g, 1.0), min(b, 1.0))
    (r, g, b) = (max(r, 0.0), max(g, 0.0), max(b, 0.0))
    return (r, g, b)

def ggColorSlice(n=12, hue=(0.004,1.00399), chroma=0.8, luma=0.6, skipHue=True) :
    # Assume:
    #   n: integer >= 1
    #   hue[from, to]: all floats - red = 0; green = 0.33333 (or -0.66667) ; blue = 0.66667 (or -0.33333)
    #   chroma[from, to]: floats all in range 0 .. 1
    #   luma[from, to]: floats all in range 0 .. 1
    # Returns a list of #rgb colour strings:

    # convert stand alone values to ranges
    if not isinstance(hue, collections.Iterable):
        hue = (hue, hue)
    if not isinstance(chroma, collections.Iterable):
        chroma = (chroma, chroma)
    if not isinstance(luma, collections.Iterable):
        luma = (luma, luma)

    # convert ints to floats
    hue = [float(hue[y]) for y in (0, 1)]
    chroma = [float(chroma[y]) for y in (0, 1)]
    luma = [float(luma[y]) for y in (0, 1)]

    # some sanity checks
    n = int(n)
    if n < 1 or n > 360 :
        raise ValueError('n is a value between 1 and 360')
    if any([chroma[y] < 0.0 or chroma[y] > 1.0 for y in (0, 1)]) :
        raise ValueError('chroma is a value between 0 and 1')
    if any([luma[y] < 0.0 or luma[y] > 1.0 for y in (0, 1)]) :
        raise ValueError('luma is a value between 0 and 1')

    # generate a list of hex colour strings
    x = n + 1 if n % 2 else n
    if n > 1 :
        lDiff = (luma[1] - luma[0]) / float(n - 1.0)
        cDiff = (chroma[1] - chroma[0]) / float(n - 1.0)
        if skipHue :
            hDiff = (hue[1] - hue[0]) / float(x)
        else :
            hDiff = (hue[1] - hue[0]) / float(x - 1.0)
    else:
        hDiff = 0.0
        lDiff = 0.0
        cDiff = 0.0

    listOfColours = []
    for i in range(n) :
        c = chroma[0] + i * cDiff
        l = luma[0] + i * lDiff
        h = math.modf(hue[0] + i * hDiff)[0]
        h = h + 1 if h < 0.0 else h
        (h, c, l) = (min(h, 0.99999999999), min(c, 1.0), min(l, 1.0))
        (h, c, l) = (max(h, 0.0), max(c, 0.0), max(l, 0.0))
        (r, g, b) = hcl_to_rgb(h, c, l)
        listOfColours.append( '#%02x%02x%02x' % (int(r*255), int(g*255), int(b*255)) )
    return listOfColours

for i in range(1, 20) :
    # made up data
    x = np.array(range(20))
    d = {}
    for j in range(1, i+1) :
        y = x * (1.0 + j/10.0) + j/10.0
        d['y'+'%03.0d' % j] = pd.Series(data=y , index=x)
    df = pd.DataFrame(d)

    # plot example
    plt.figure(num=1, figsize=(10,5), dpi=100) # set default image size
    colours = ggColorSlice(n=i)
    if len(colours) == 1:
        colours = colours[0] # kludge
    df.plot(linewidth=4.0, color=colours)
    fig = plt.gcf()
    f = 'test-'+str(i)+'.png'
    print f
    plt.title(f)
    fig.savefig(f)
    plt.close()
将熊猫作为pd导入
将numpy作为np导入
将matplotlib.pyplot作为plt导入
输入数学
导入集合
def hcl_至_rgb(色调=0,色度=0,亮度=0):
#注:
#编码自http://en.wikipedia.org/wiki/HSL_and_HSV#From_luma.2Fchroma.2Fhue
#借助MagickCore 6.7.8中gem.c的见解
#   http://www.imagemagick.org/api/MagickCore/gem_8c_source.html
#假设:
#h、c、l均在0范围内。。1(柱坐标)
#返回一个元组:
#r、g、b均在0范围内。。1(三次笛卡尔坐标)
#健康检查
hue=math.modf(float(hue))[0]
如果色调<0或色调>=1:
raise VALUERROR('色调是大于或等于0且小于1'的值)
色度=浮动(色度)
如果色度<0或色度>1:
raise VALUERROR('色度是介于0和1'之间的值)
luma=浮动(luma)
如果luma<0或luma>1:
raise VALUERROR('luma是介于0和1'之间的值)
#进行转换
_h=色调*6.0
x=色度*(1-abs((_h%2)-1))
c=色度

如果0您将希望沿HUSL颜色空间的色调维度均匀采样,这是一个很好的选择。这就是seaborn中使用的功能。

+1。我还想建议Seaborn:;Python-ggplot:;还有prettyplotlib:@PaulH我认为这是值得的answer@PaulH是的,请写这个作为一个新的答案,这些都是伟大的软件包!仔细看gg代码——看起来我有两个问题。第一个是分母应该是n+1,而不是n。第二个问题是我需要一个色相-色度-亮度转换工具;而不是我一直采用的色调-亮度饱和度方法。不幸的是,我不知道python中有hclTOrgb工具。