python - 如何使用熊猫图获得两个图例,一个用于堆叠条的颜色,一个用于条的阴影?
问题描述
我一直试图理解这篇文章的答案,以便填充两个不同的传说。
我为每个条创建了一个带有不同阴影的聚集堆积条图,下面的代码与上述帖子的答案有点不同。
但是我无法弄清楚如何获得一个带有颜色的图例和一个带有阴影的图例。
颜色图例应对应于 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)
我设法得到的情节是:
任何想法如何创建两个图例并将它们放在另一个旁边或一个在另一个下面?提前谢谢^_^
解决方案
由于添加图例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
:height
rect.set_height(1 / float(n_df + 1))
- 调整
axe.set_xticks
和axe.set_xticklabels
值np.arange(0, 120, 20)
_
功能
import numpy as np
import pandas as pd
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap as coloring
def 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()
输出
推荐阅读
- node.js - Nodemailer 和后缀
- javascript - 如何从表单提交中生成 DIV 表?
- python - 如何在我的程序末尾读取带有时间戳的文件
- php - 将 Woocommerce 结帐更改为在单独的 WordPress 网站上处理订单?
- c++ - 用于比较数组的函数太少
- javascript - 我如何向一个 ID 显示多个 if/else?
- ruby-on-rails - Rails在构建关联对象时重用ID?
- java - 我的问题的最佳 OOP 解决方案是什么?
- azure-devops - 我的 Azure DevOps 组织与哪个 Azure AD 相关联?
- javascript - 对烧瓶 render_template 进行 AJAX 调用时出现问题