【问题标题】:Single legend for multiple barplots matplotlib多个条形图的单个图例 matplotlib
【发布时间】:2017-06-11 23:12:26
【问题描述】:

我有一个使用 pandas Dataframe 中的不同列创建的多个条形图。

fig1 = plt.figure()
ypos = np.arange(len(dframe))

colorscheme = seaborn.color_palette(n_colors=4)

accuracyFig = fig1.add_subplot(221)
accuracyFig.bar(ypos,dframe['accuracy'], align = 'center', color=colorscheme)
accuracyFig.set_xticks([0,1,2,3])
accuracyFig.set_ylim([0.5,1])

sensitivityFig = fig1.add_subplot(222)
sensitivityFig.bar(ypos, dframe['sensitivity'], align = 'center',color=colorscheme )
sensitivityFig.set_xticks([0,1,2,3])
sensitivityFig.set_ylim([0.5,1])

specificityFig = fig1.add_subplot(223)
specificityFig.bar(ypos, dframe['specificity'], align = 'center', color=colorscheme)
specificityFig.set_xticks([0,1,2,3])
specificityFig.set_ylim([0.5,1])

precisionFig = fig1.add_subplot(224)
precisionFig.bar(ypos, dframe['precision'], align = 'center', color=colorscheme)
precisionFig.set_xticks([0,1,2,3])
precisionFig.set_ylim([0.5,1])

其中dframe 是具有整数值的熊猫数据框。这给我输出了下图

每种颜色对应一个分类器模型 - perceptron,C2,C3 and C4,它们存储在熊猫dframe['name']

现在我想为整个图形绘制一个图例。我尝试了以下

leg = plt.legend(dframe['name'])

关于如何绘制单个图例并将其放在图下方 2 列中的任何帮助。

但它给了我以下

这是我的数据框

                     name        accuracy     sensitivity     specificity       precision
0              perceptron  0.820182164169  0.852518881235  0.755172413793  0.875007098643
1  DecisionTreeClassifier             1.0             1.0             1.0             1.0
2    ExtraTreesClassifier             1.0             1.0             1.0             1.0
3  RandomForestClassifier  0.999796774253  0.999889340748  0.999610678532  0.999806362379

【问题讨论】:

  • 将图例下方的图例放置为2X2矩阵而不是1X4向量
  • 它只显示感知器标签,其余标签不显示。就像上图一样
  • 添加到问题中
  • [['perceptron', 'DecisionTreeClassifier', 'ExtraTreesClassifier', 'RandomForestClassifier'], [0.82018216416945333, 1.0, 1.0, 0.99979677425314539], [0.85251888123495723, 1.0, 1.0, 0.99988934074750324], [0.7551724137931034, 1.0, 1.0, 0.99961067853170193], [0.87500709864273951, 1.0, 1.0, 0.99980636237897647]]
  • 我已使用dframe.values.T.tolist()将其转换为列表

标签: python pandas matplotlib dataframe seaborn


【解决方案1】:

首先,您的表格格式不整齐(请参阅此处:http://vita.had.co.nz/papers/tidy-data.pdf)。

让你的表格整齐(或长)格式具有巨大的优势,即使用 seaborn 绘图变得非常容易(以及其他优势):

df # yours
                     name        accuracy     sensitivity     specificity       precision
0              perceptron  0.820182164169  0.852518881235  0.755172413793  0.875007098643
1  DecisionTreeClassifier             1.0             1.0             1.0             1.0
2    ExtraTreesClassifier             1.0             1.0             1.0             1.0
3  RandomForestClassifier  0.999796774253  0.999889340748  0.999610678532  0.999806362379

将其转换为长格式(或整齐):

df2 = pd.melt(df, value_vars=["accuracy", "sensitivity", "specificity", "precision"], id_vars="name")
df2
                      name     variable     value
0               perceptron     accuracy  0.820182
1   DecisionTreeClassifier     accuracy  1.000000
2     ExtraTreesClassifier     accuracy  1.000000
3   RandomForestClassifier     accuracy  0.999797
4               perceptron  sensitivity  0.852519
5   DecisionTreeClassifier  sensitivity  1.000000
6     ExtraTreesClassifier  sensitivity  1.000000
7   RandomForestClassifier  sensitivity  0.999889
8               perceptron  specificity  0.755172
9   DecisionTreeClassifier  specificity  1.000000
10    ExtraTreesClassifier  specificity  1.000000
11  RandomForestClassifier  specificity  0.999611
12              perceptron    precision  0.875007
13  DecisionTreeClassifier    precision  1.000000
14    ExtraTreesClassifier    precision  1.000000
15  RandomForestClassifier    precision  0.999806

然后,只需在一行 + 2 行中绘制您想要的内容以使其更清晰:

g = sns.factorplot(data=df2,
                   kind="bar",
                   col="variable", # you have 1 plot per variable, forming 1 line and 4 columns (4 different variables)
                   x="name", # in each plot the x-axis will be the name
                   y="value", # the height of the bar
                   col_wrap=2) # you actually want your line of plots to contain 2 plots maximum 
g.set_xticklabels(rotation=90) # rotate the labels so they don't overlap
plt.tight_layout() # fit everything into the figure

HTH

【讨论】:

  • 哦,太好了。
【解决方案2】:

您可以使用以下方法将图例移动到图表中需要的位置。

在绘制条形图时添加标签是必要的。我已经更改了您绘制图例的主线。

我添加了一些虚拟标签,在您的代码中,您可以通过 labels = list(df) 为您提供数据框中的列名列表来获取标签。

import matplotlib.pyplot as plt

colorscheme = ['r','b','c','y']
fig1 = plt.figure()
accuracyFig = fig1.add_subplot(221)
A =[1,2,3,4]
B = [4,3,2,1]
labels = ['perceptron','C2','C3','C4']
for i in range(0,len(A)):
    accuracyFig.bar(A[i],B[i], align = 'center',label = labels[i], color = colorscheme[i])

accuracyFig1 = fig1.add_subplot(223)
A =[1,2,3,4]
B = [4,3,2,1]
labels = ['perceptron','C2','C3','C4']
for i in range(0,len(A)):
    accuracyFig1.bar(A[i],B[i], align = 'center',label = labels[i], color = colorscheme[i])

accuracyFig2 = fig1.add_subplot(222)
A =[1,2,3,4]
B = [4,3,2,1]
labels = ['perceptron','C2','C3','C4']
for i in range(0,len(A)):
    accuracyFig2.bar(A[i],B[i], align = 'center',label = labels[i], color = colorscheme[i])

accuracyFig3 = fig1.add_subplot(224)
A =[1,2,3,4]
B = [4,3,2,1]
labels = ['perceptron','C2','C3','C4']
for i in range(0,len(A)):
    accuracyFig3.bar(A[i],B[i], align = 'center',label = labels[i], color = colorscheme[i])

# Plot the legend:
# You don't want to plot to any particular axis, instead to a general plot.

plt.legend(loc = 'lower center',bbox_to_anchor = (0,-0.3,1,1),
        bbox_transform = plt.gcf().transFigure)
plt.show()

图例来源:

How to create custom legend in matplotlib based on the value of the barplot? how do I make a single legend for many subplots with matplotlib? How to put the legend out of the plot

更新:意外删除了我的 cmets:在 legend() 中添加 ncol = 2 将提供您想要的对称拆分行为。

【讨论】:

    【解决方案3】:

    我将代码修改如下

    fig1 = plt.figure()
    
    A = list(range(1,len(dframe)+1))
    labels = dframe['name'].tolist()
    
    colorscheme = sns.color_palette(n_colors=len(dframe))
    
    
    accuracyFig = fig1.add_subplot(221)
    for i in range(0,len(A)):
        accuracyFig.bar(A[i],dframe['accuracy'][i+1], align = 'center',label = labels[i], color = colorscheme[i])
    accuracyFig.set_xticks([])
    accuracyFig.set_ylim([0.5,1])
    accuracyFig.set_title('Accuracy')
    
    sensitivityFig = fig1.add_subplot(222)
    for i in range(0,len(A)):
        sensitivityFig.bar(A[i],dframe['sensitivity'][i+1], align = 'center',label = labels[i], color = colorscheme[i])
    sensitivityFig.set_xticks([])
    sensitivityFig.set_ylim([0.5,1])
    sensitivityFig.set_title('Sensitivity')
    
    specificityFig = fig1.add_subplot(223)
    for i in range(0,len(A)):
        specificityFig.bar(A[i],dframe['specificity'][i+1], align = 'center',label = labels[i], color = colorscheme[i])
    specificityFig.set_xticks([])
    specificityFig.set_ylim([0.5,1])
    specificityFig.set_title('Specificity')
    
    precisionFig = fig1.add_subplot(224)
    for i in range(0,len(A)):
        precisionFig.bar(A[i],dframe['precision'][i+1], align = 'center',label = labels[i], color = colorscheme[i])
    precisionFig.set_xticks([])
    precisionFig.set_ylim([0.5,1])
    precisionFig.set_title('Precision')
    
    # Plot the legend:
    
    plt.legend(loc = 'lower center',bbox_to_anchor = (0,-0.05,1,2), ncol=2,
            bbox_transform = plt.gcf().transFigure)
    
    plt.show()
    

    我没有使用固定长度的标签,而是直接从数据框中复制它们并且它可以工作。

    我做了一些更新并将参数(n_cols = 2)添加到图例函数中,这样我的输出图看起来像这样

    感谢@Charles Morris 的帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 2022-01-10
      相关资源
      最近更新 更多