用于重叠透明区域的自定义图例在 python pandas 数据帧中为stacked=false 具有精确的颜色? [英] Custom legend for overlapping transparent areas with exact colors in a python pandas dataframe for stacked=false?

查看:103
本文介绍了用于重叠透明区域的自定义图例在 python pandas 数据帧中为stacked=false 具有精确的颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用(我使用了稍微不同的alpha计算),我得到的是这样的:

为了更容易地比较图例项与重叠圆圈的混合颜色,我将图例项用 Photoshop 处理到图中(圆圈边缘的小方块).

 将matplotlib.pyplot导入为plt从matplotlib.lines导入Line2Dplt.figure()# cf = 前景色,cb = 背景色def mix_colors(cf,cb):a = cb [-1] + cf [-1]-cb [-1] * cf [-1]#固定的alpha计算r = (cf[0] * cf[-1] + cb[0] * cb[-1] * (1 - cf[-1]))/ag = (cf[1] * cf[-1] + cb[1] * cb[-1] * (1 - cf[-1]))/ab =(cf [2] * cf [-1] + cb [2] * cb [-1] *(1-cf [-1]))/a返回[r,g,b,a]c1 = [1.0,0.1,0.1,0.5]c2 = [0.3,0.2,0.7,0.5]c3 = [0.5,0.8,0.5,0.5]c12 = mix_colors(c2,c1)#在c1上混合c2c13 = mix_colors(c3, c1) # 在 c1 上混合 c3c123 = mix_colors(c3, c12) # 在 c12 上混合 c3circle1 = plt.Circle((3,3),radius = 3,fc = c1,edgecolor = None)circle2 = plt.Circle((3,7),radius = 3,fc = c2,edgecolor = None)circle3 = plt.Circle((6,5),radius = 3,fc = c3,edgecolor = None)圆圈 = [圆圈 1,圆圈 2,圆圈 3]对于圈子中的牧师:plt.gca().add_patch(cle)plt.axis('scaled')plt.xlim(0,10)circ1 = Line2D([0], [0], linestyle='none', marker='s',标记大小=10,标记面颜色=c1)circ2 = Line2D([0], [0], linestyle='none', marker='s',标记大小=10,标记面颜色=c2)circ3 = Line2D([0],[0],linestyle ='none',marker ='s',markersize = 10,markerfacecolor = c3)circ4 = Line2D([0],[0],linestyle ='none',marker ='s',标记大小=10,标记面颜色=c12)circ5 = Line2D([0],[0],linestyle ='none',marker ='s',markersize = 10,markerfacecolor = c13)circ6 = Line2D([0],[0],linestyle ='none',marker ='s',标记大小=10,标记面颜色=c123)plt.legend((circ1,circ2,circ3,circ4,circ5,circ6),('A','B','C','AB','AC','ABC'),numpoints = 1,loc ='最好的')

When producing an unstacked area plot with pandas dataframe.plot, one gets more colored surfaces than the number of legend entries.

Consider:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(11, 3)+3, columns=['A', 'B', 'C'])

with

>>> print df

giving e.g.:

           A         B         C
0   1.908785  2.516292  4.139940
1   2.566306  3.275534  3.889655
2   2.083525  2.554483  3.565328
3   1.406931  2.021886  2.956590
4   3.293099  3.672927  3.203007
5   3.542735  1.301354  3.259613
6   1.331992  4.882820  2.165666
7   2.670735  3.763886  3.290484
8   4.211895  0.923923  3.415861
9   3.664398  2.009058  2.436214
10  2.707552  3.149282  1.629846

and

df.plot(kind='area', stacked=False)

producing:

With three data series, or columns in the dataframe, there are seven differently colored surfaces: With A,B,C as the basis, there are the pairs AB, AC, BC, and the overlap of all: ABC.

Trying to visualize this in the pyplot with overlapping circles as follows:

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plt.figure()

circle1 = plt.Circle((3, 3), radius=3, fc='r', alpha=0.5, edgecolor=None)
circle2 = plt.Circle((3, 7), radius=3, fc='g', alpha=0.5, edgecolor=None)
circle3 = plt.Circle((6, 5), radius=3, fc='b', alpha=0.5, edgecolor=None)
circles = [circle1, circle2, circle3]
for cle in circles:
    plt.gca().add_patch(cle)

plt.axis('scaled')
plt.xlim(0, 10)

Now, I learned how to make a custom legend with specific colors in pyplot with line2D objects as follows:

circ1 = Line2D([0], [0], linestyle='none', marker='s', alpha=0.5,
               markersize=10, markerfacecolor='r')
circ2 = Line2D([0], [0], linestyle='none', marker='s', alpha=0.5,
               markersize=10, markerfacecolor='g')
circ3 = Line2D([0], [0], linestyle='none', marker='s', alpha=0.5,
               markersize=10, markerfacecolor="blue")

plt.legend((circ1, circ2, circ3), ('A', 'B', 'C'), numpoints=1, loc='best')

yielding the following output:

But how does one access the exact colors for the overlapping surfaces from the original pandas plot of unstacked areas, providing a means to create a legend with seven entries?

Please also note that the colors here are slightly different. While on the one hand in pandas the additive coloring produces darker shades of red (although this seems to vary with the number of data series/columns of the dataframe plotted), on the other hand pyplot produces darker shades of blue.

解决方案

You could manully calculate the blended color. For example, with the algorithm I found here (I used a slightly different alpha calculation), I get something like this:

For an easier comparison of the legend items with the blended color of the overlapping circles, I Photoshopped the legend items into the figure (small squares at the edges of the circles).

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

plt.figure()

# cf = foreground color, cb = background color 
def mix_colors(cf, cb):
    a = cb[-1] + cf[-1] - cb[-1] * cf[-1] # fixed alpha calculation
    r = (cf[0] * cf[-1] + cb[0] * cb[-1] * (1 - cf[-1])) / a
    g = (cf[1] * cf[-1] + cb[1] * cb[-1] * (1 - cf[-1])) / a
    b = (cf[2] * cf[-1] + cb[2] * cb[-1] * (1 - cf[-1])) / a
    return [r,g,b,a]

c1 = [1.0, 0.1, 0.1, 0.5]
c2 = [0.3, 0.2, 0.7, 0.5]
c3 = [0.5, 0.8, 0.5, 0.5]

c12  = mix_colors(c2, c1) # mix c2 over c1
c13  = mix_colors(c3, c1) # mix c3 over c1
c123 = mix_colors(c3, c12) # mix c3 over c12

circle1 = plt.Circle((3, 3), radius=3, fc=c1, edgecolor=None)
circle2 = plt.Circle((3, 7), radius=3, fc=c2, edgecolor=None)
circle3 = plt.Circle((6, 5), radius=3, fc=c3, edgecolor=None)
circles = [circle1, circle2, circle3]
for cle in circles:
    plt.gca().add_patch(cle)

plt.axis('scaled')
plt.xlim(0, 10)

circ1 = Line2D([0], [0], linestyle='none', marker='s',
               markersize=10, markerfacecolor=c1)
circ2 = Line2D([0], [0], linestyle='none', marker='s',
               markersize=10, markerfacecolor=c2)
circ3 = Line2D([0], [0], linestyle='none', marker='s',
               markersize=10, markerfacecolor=c3)
circ4 = Line2D([0], [0], linestyle='none', marker='s',
               markersize=10, markerfacecolor=c12)
circ5 = Line2D([0], [0], linestyle='none', marker='s',
               markersize=10, markerfacecolor=c13)
circ6 = Line2D([0], [0], linestyle='none', marker='s',
               markersize=10, markerfacecolor=c123)

plt.legend((circ1, circ2, circ3, circ4, circ5, circ6), ('A', 'B', 'C', 'AB', 'AC', 'ABC'), numpoints=1, loc='best')

这篇关于用于重叠透明区域的自定义图例在 python pandas 数据帧中为stacked=false 具有精确的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆