如何使用熊猫图获得两个图例,一个用于堆叠条的颜色,一个用于条的阴影?

我一直试图理解这篇文章的答案,以便填充两个不同的传说。


我为每个条创建了一个带有不同阴影的聚集堆积条图,下面的代码与上述帖子的答案有点不同。


但是我无法弄清楚如何获得一个带有颜色的图例和一个带有阴影的图例。


颜色图例应对应于 A、B、C、D、E,并且阴影图例应指示“有”如果条带阴影线,“无”如果没有阴影线。


import matplotlib.pyplot as plt

from matplotlib.colors import LinearSegmentedColormap as coloring


# copy the dfs below and use pd.read_clipboard() to reproduce

df_1

     A   B   C   D   E

Mg  10  15  23  25  27

Ca  30  33   0  20  17


df_2

     A   B   C   D   E

Mg  20  12   8  40  10

Ca   7  26  12  22  16


hatches=(' ', '//')

colors_ABCDE=['tomato', 'gold', 'greenyellow', 'forestgreen', 'palevioletred']

dfs=[df_1,df_2]


for each_df, df in enumerate(dfs):

    df.plot(ax=plt.subplot(111), kind="barh", \

            stacked=True, hatch=hatches[each_df], \

            colormap=coloring.from_list("my_colormap", colors_ABCDE), \

            figsize=(7,2.5), position=len(dfs)-each_df-1, \

            align='center', width=0.2, edgecolor="darkgrey")


plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5), fontsize=12)

我设法得到的情节是:

http://img2.mukewang.com/634e49e50001d76804840207.jpg

任何想法如何创建两个图例并将它们放在另一个旁边或一个在另一个下面?提前谢谢^_^



MM们
浏览 137回答 2
2回答

白猪掌柜的

由于添加图例matplotlib是一个复杂而广泛的步骤,因此请考虑使用您引用的 @jrjc函数解决方案的链接。但是,您需要根据水平条形图的需要调整功能。具体来说:为颜色图和DataFrame.plot调用添加参数将条形图从kind='bar'到调整kind='barh'为水平版本将 x 换成 y 行:rect.set_y(rect.get_y() + 1 / float(n_df + 1) * i / float(n_col))换线width:heightrect.set_height(1 / float(n_df + 1))调整axe.set_xticks和axe.set_xticklabels值np.arange(0, 120, 20)_功能import numpy as npimport pandas as pdimport matplotlib.cm as cmimport matplotlib.pyplot as pltfrom matplotlib.colors import LinearSegmentedColormap as coloringdef plot_clustered_stacked(dfall, labels=None, title="multiple stacked bar plot", H="//",                            colors_ABCDE=['tomato', 'gold', 'greenyellow', 'forestgreen', 'palevioletred'], **kwargs):    """       CREDIT: @jrjc (https://stackoverflow.com/a/22845857/1422451)       Given a list of dataframes, with identical columns and index, create a clustered stacked bar plot.        labels is a list of the names of the dataframe, used for the legend       title is a string for the title of the plot       H is the hatch used for identification of the different dataframe    """    n_df = len(dfall)    n_col = len(dfall[0].columns)     n_ind = len(dfall[0].index)    axe = plt.subplot(111)    for df in dfall : # for each data frame        axe = df.plot(kind="barh",                      linewidth=0,                      stacked=True,                      ax=axe,                      legend=False,                      grid=False,                      colormap=coloring.from_list("my_colormap", colors_ABCDE),                      edgecolor="darkgrey",                      **kwargs)  # make bar plots    h,l = axe.get_legend_handles_labels() # get the handles we want to modify    for i in range(0, n_df * n_col, n_col): # len(h) = n_col * n_df        for j, pa in enumerate(h[i:i+n_col]):            for rect in pa.patches: # for each index                rect.set_y(rect.get_y() + 1 / float(n_df + 2) * i / float(n_col))                rect.set_hatch(H * int(i / n_col)) #edited part                     rect.set_height(1 / float(n_df + 2))    axe.set_xticks(np.arange(0, 125, 20))    axe.set_xticklabels(np.arange(0, 125, 20).tolist(), rotation = 0)    axe.margins(x=0, tight=None)    axe.set_title(title)    # Add invisible data to add another legend    n=[]            for i in range(n_df):        n.append(axe.bar(0, 0, color="gray", hatch=H * i, edgecolor="darkgrey"))    l1 = axe.legend(h[:n_col], l[:n_col], loc=[1.01, 0.5])    if labels is not None:        l2 = plt.legend(n, labels, loc=[1.01, 0.1])     axe.add_artist(l1)    return axe称呼plt.figure(figsize=(10, 4))plot_clustered_stacked([df_1, df_2],["df_1", "df_2"])plt.show()plt.clf()plt.close()输出

慕慕森

我认为@jrjc 的这个功能解决方案对我的理解来说相当令人困惑,因此,我更愿意稍微改变我自己的东西并进行调整。所以,我花了一些时间才明白,当为情节创建第二个图例时,python 会自动删除第一个图例,这是add_artist()必须使用的时候。添加第二个图例的另一个先决条件是命名图并将 .add_artist() 方法应用于该特定图,以便 python 知道将新部分粘贴在哪里。简而言之,这就是我设法创建我想到的情节的方式,我希望这些评论能让它更清晰,对任何人都有用。import matplotlib.pyplot as pltfrom matplotlib.colors import LinearSegmentedColormap as coloringimport matplotlib.patches as mpatches# copy the dfs below and use pd.read_clipboard() to reproducedf_1     A   B   C   D   EMg  10  15  23  25  27Ca  30  33   0  20  17df_2     A   B   C   D   EMg  20  12   8  40  10Ca   7  26  12  22  16hatches=(' ', '//')colors_ABCDE=['tomato', 'gold', 'greenyellow', 'forestgreen', 'palevioletred']dfs=[df_1,df_2]for each_df, df in enumerate(dfs):    #I name the plot as "figure"    figure=df.plot(ax=plt.subplot(111), kind="barh", \            stacked=True, hatch=hatches[each_df], \            colormap=coloring.from_list("my_colormap", colors_ABCDE), \            figsize=(7,2.5), position=len(dfs)-each_df-1, \            align='center', width=0.2, edgecolor="darkgrey", \            legend=False) #I had to False the legend toolegend_1=plt.legend(df_1.columns, loc='center left', bbox_to_anchor=(1.0, 0.5), fontsize=12)patch_hatched = mpatches.Patch(facecolor='beige', hatch='///', edgecolor="darkgrey", label='hatched')patch_unhatched = mpatches.Patch(facecolor='beige', hatch=' ', edgecolor="darkgrey", label='non-hatched')legend_2=plt.legend(handles=[patch_hatched, patch_unhatched], loc='center left', bbox_to_anchor=(1.15, 0.5), fontsize=12)# as soon as a second legend is made, the first disappears and needs to be added back againfigure.add_artist(legend_1) #python now knows that "figure" must take the "legend_1" along with "legend_2"有两个传说的情节我很确定它可以更加优雅和自动化。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python