matplotlib绘图优化–表格与柱状图结合

  • A+
所属分类:python数据分析
摘要这一篇主要介绍如何绘制表格与柱状图结合的例子. 一般可以用这种类型的图来表示不同模型之间的比较.

简介

有的时候看论文的时候, 会看到表格与柱状图结合的例子, 像下面这样. 这一篇我们就来使用matplotlib来复现一下这种图像.

matplotlib绘图优化–表格与柱状图结合

参考链接

 

表格与柱状图结合的简单例子

下面简单看一下使用matplotlib来实现表格与柱状图结合. 首先导入需要的库. 关于完整的代码, 可以参考链接, 绘制表格与柱状图.ipynb.

  1. import numpy as np
  2. import pandas as pd
  3. import matplotlib.pyplot as plt

 

生成测试数据

首先我们生成需要的测试数据. 假设我们现在有5个模型, 有4个评测指标, 得到了如下的数据.

  1. data = [[ 66386, 174296,  75131, 577908,  32015],
  2.         [ 58230, 381139,  78045,  99308, 160454],
  3.         [ 89135,  80552, 152558, 497981, 603535],
  4.         [ 78415,  81858, 150656, 193263,  69638]]
  5. columns = ('Model 1', 'Model 2', 'Model 3', 'Model 4', 'Model 5')
  6. rows = ['Metric %d' % x for x in (1, 2, 3, 4)]
  7. pltPD = pd.DataFrame(data, columns=columns, index=rows)
  8. pltPD

得到的表格如下所示, 一般情况下, 如果比较不同模型之间的结果, 都会有如下的表格:

matplotlib绘图优化–表格与柱状图结合

 

按照模型进行汇总绘制

首先我们按照模型进行绘制. 将同一个模型的不同指标绘制在一起. 下面是完整的代码. 我们简单说一下需要注意的点:

  • 绘制这种图像就是首先绘制柱状图, 接着绘制table, 把这两个和在一起.
  • 自定义颜色, colors, 是用来指定柱状图的颜色, 这个颜色会和下面表格中的颜色对应.
  • 我们会对矩阵也进行高亮, 为了更加突出颜色的分布, 我们会对数据进行最大最小标准化, 即(x-min)/(max-min).
  • 最后需要注意, 需要把xticks设置为空.

同时, 我们要使用下面的代码对表格里的文字进行适当的放大. 这里scale中的1.7是纵向进行拉伸.

  1. the_table.set_fontsize(14)
  2. the_table.scale(1.0, 1.7)  # may help

下面是完整的代码.

  1. # 按照model来进行汇总, 这里共有5个model
  2. fig = plt.figure(figsize=(12,8))
  3. ax = fig.add_subplot(1,1,1)
  4. # 自定义颜色
  5. # colors = plt.cm.BuPu(np.linspace(0, 0.5, len(pltPD.index.values)))
  6. colors = plt.cm.rainbow(np.linspace(0, 1, len(pltPD.index.values))) # plasma, rainbow, jet
  7. n_rows = len(pltPD.index.values)
  8. # 设置barchart的x轴
  9. w=0.3
  10. index = np.arange(len(pltPD.columns.values))*n_rows*w*1.5 # 5个model, 所以是5
  11. # 首先绘制柱状图
  12. for row in range(n_rows):
  13.     plt.bar(index+row*w, pltPD.values[row], width=w, align='center', color=colors[row], label=pltPD.index.values[row])
  14. # 添加图例
  15. ax.legend(fontsize=12)
  16. # 矩阵的颜色高亮
  17. # norm = plt.Normalize(0, 1)
  18. # cellColours = plt.cm.Blues(norm(pltPD.values))
  19. # 使用最大最小标准化, 使得颜色区分更大
  20. minmax = (pltPD.values - pltPD.values.min(1, keepdims=True)) / (pltPD.values.max(1, keepdims=True) - pltPD.values.min(1, keepdims=True))
  21. cellColours = plt.cm.Blues(minmax)
  22. # 添加一个表格在底部
  23. the_table = plt.table(cellText=pltPD.values,
  24.                       cellColours = cellColours,
  25.                       rowLabels=pltPD.index.values,
  26.                       rowColours=colors, # 每一列的颜色
  27.                       colLabels=pltPD.columns.values,
  28.                       loc='bottom',
  29.                       cellLoc='center')
  30. the_table.set_fontsize(14)
  31. the_table.scale(1.0, 1.7)  # may help
  32. # 调整table的布局
  33. # plt.subplots_adjust(left=0.2, bottom=0.1)
  34. # label和ticks的设置
  35. # minN, maxN = pltPD.values.flatten().min(), pltPD.values.flatten().max()
  36. # plt.yticks(np.arange(minN, maxN, (maxN-minN)/5), fontsize=14)
  37. plt.yticks(np.arange(0, 1.1, 0.2), fontsize=14)
  38. plt.xticks([])
  39. plt.title('Comparison between Different Models', fontsize=14)
  40. plt.show()

最终绘制出来的图像如下图所示, 有几个点我们再强调一下:

  • 下图是按照模型来进行汇总的, 同一个model的4个不同的指标会放在一起;
  • 柱状图不同的颜色对应不同的指标, 这里的颜色是和下面table中的颜色是对应的;
matplotlib绘图优化–表格与柱状图结合

 

按照评价指标进行汇总绘制

上面我们是按照模型进行汇总, 也就是同一个模型的不同的指标放在一起. 那么我们也可以按照指标来进行汇总. 例如将同一个模型的不同指标放在一起.

这里和上面代码几乎是一样的, 我们只需要对原始的矩阵进行转置操作即可.

  1. # 按照metric来进行汇总, 这里共有4种metric, 可以很容易比较模型的好坏
  2. fig = plt.figure(figsize=(12,8))
  3. ax = fig.add_subplot(1,1,1)
  4. # 进行转置
  5. pltPD = pltPD.T
  6. # 自定义颜色
  7. # colors = plt.cm.BuPu(np.linspace(0, 0.5, len(pltPD.index.values)))
  8. colors = plt.cm.rainbow(np.linspace(0, 1, len(pltPD.index.values))) # plasma, rainbow, jet
  9. n_rows = len(pltPD.index.values)
  10. # 设置barchart的x轴
  11. w=0.3
  12. index = np.arange(len(pltPD.columns.values))*n_rows*w*1.5 # 5个model, 所以是5
  13. # 首先绘制柱状图
  14. for row in range(n_rows):
  15.     plt.bar(index+row*w, pltPD.values[row], width=w, align='center', color=colors[row], label=pltPD.index.values[row])
  16. # 添加图例
  17. ax.legend(fontsize=12, loc='upper left')
  18. # 矩阵的颜色高亮
  19. # norm = plt.Normalize(pltPD.values.min(), pltPD.values.max())
  20. # cellColours = plt.cm.Blues(norm(pltPD.values))
  21. minmax = (pltPD.values - pltPD.values.min(1, keepdims=True)) / (pltPD.values.max(1, keepdims=True) - pltPD.values.min(1, keepdims=True))
  22. cellColours = plt.cm.Blues(minmax)
  23. # 添加一个表格在底部
  24. the_table = plt.table(cellText=pltPD.values,
  25.                       cellColours=cellColours,
  26.                       rowLabels=pltPD.index.values,
  27.                       rowColours=colors, # 每一列的颜色
  28.                       colLabels=pltPD.columns.values,
  29.                       loc='bottom',
  30.                       cellLoc='center')
  31. the_table.set_fontsize(14)
  32. the_table.scale(1.0, 1.7)  # may help
  33. # 调整table的布局
  34. # plt.subplots_adjust(left=0.2, bottom=0.1)
  35. # label和ticks的设置
  36. # minN, maxN = pltPD.values.flatten().min(), pltPD.values.flatten().max()
  37. plt.yticks(np.arange(0, 1.1, 0.2), fontsize=14)
  38. plt.xticks([])
  39. plt.title('Comparison between Different Models', fontsize=14)
  40. plt.show()

最终可以得到下面的图像, 可以看到这样就是相同的评价指标会在一起. 这样很容易比较, 同一个评价指标, 哪一个模型是最好的.

matplotlib绘图优化–表格与柱状图结合

 

表格双标题的情况(double headers)

上面说了最基础的绘制柱状图与表格结合的情况. 下面给一个例子, 当我们的table比较复杂的时候, 即拥有double headers的时候, 应该如何处理.

参考链接: Matplotlib table with double headers

其实主要的想法很简单, 我们同时添加多个table, 然后通过bbox来控制表格的位置即可. 这里说一下bbox的参数, 分别是(x0, y0, width, height). 需要注意的是, 这里(x0,y0)相当于矩形的左下角的点.

  1. header = plt.table(cellText=[['']*2],
  2.                    colLabels=['$\\bf{\lambda=0.02}$', '$\\bf{\lambda=0.99}$'],
  3.                    loc='bottom',
  4.                    cellLoc='center',
  5.                    bbox=[0, -0.2, 0.8, 0.2] # x0, y0, width, height
  6.                    )
  7. header.set_fontsize(14)
  8. header.scale(1.0, 1.7)  # may help
  9. header_1 = plt.table(cellText=[['']],
  10.                      colLabels=['$\\bf{RL}$'],
  11.                      loc='bottom',
  12.                      cellLoc='center',
  13.                      bbox=[0.8, -0.2, 0.2, 0.2]
  14.                      )
  15. header_1.set_fontsize(14)
  16. header_1.scale(1.0, 1.7)  # may help

下面是完整的代码, 我们只需要添加上面的部分即可, 剩下的都是一样的.

  1. # 按照model来进行汇总, 这里共有5个model
  2. fig = plt.figure(figsize=(12,8))
  3. ax = fig.add_subplot(1,1,1)
  4. # 自定义颜色
  5. # colors = plt.cm.BuPu(np.linspace(0, 0.5, len(pltPD.index.values)))
  6. colors = plt.cm.rainbow(np.linspace(0, 1, len(pltPD.index.values))) # plasma, rainbow, jet
  7. n_rows = len(pltPD.index.values)
  8. # 设置barchart的x轴
  9. w=0.3
  10. index = np.arange(len(pltPD.columns.values))*n_rows*w*1.5 # 5个model, 所以是5
  11. # 首先绘制柱状图
  12. for row in range(n_rows):
  13.     plt.bar(index+row*w, pltPD.values[row], width=w, align='center', color=colors[row], label=pltPD.index.values[row])
  14. # 添加图例
  15. ax.legend(fontsize=12)
  16. # 矩阵的颜色高亮
  17. # norm = plt.Normalize(0, 1)
  18. # cellColours = plt.cm.Blues(norm(pltPD.values))
  19. # 使用最大最小标准化, 使得颜色区分更大
  20. minmax = (pltPD.values - pltPD.values.min(1, keepdims=True)) / (pltPD.values.max(1, keepdims=True) - pltPD.values.min(1, keepdims=True))
  21. cellColours = plt.cm.Blues(minmax)
  22. # 给表格添加一个标题
  23. header = plt.table(cellText=[['']*2],
  24.                    colLabels=['$\\bf{\lambda=0.02}$', '$\\bf{\lambda=0.99}$'],
  25.                    loc='bottom',
  26.                    cellLoc='center',
  27.                    bbox=[0, -0.2, 0.8, 0.2] # x0, y0, width, height
  28.                    )
  29. header.set_fontsize(14)
  30. header.scale(1.0, 1.7)  # may help
  31. header_1 = plt.table(cellText=[['']],
  32.                      colLabels=['$\\bf{RL}$'],
  33.                      loc='bottom',
  34.                      cellLoc='center',
  35.                      bbox=[0.8, -0.2, 0.2, 0.2]
  36.                      )
  37. header_1.set_fontsize(14)
  38. header_1.scale(1.0, 1.7)  # may help
  39. # 添加一个表格在底部
  40. the_table = plt.table(cellText=pltPD.values,
  41.                       cellColours = cellColours,
  42.                       rowLabels=pltPD.index.values,
  43.                       rowColours=colors, # 每一列的颜色
  44.                       colLabels=pltPD.columns.values,
  45.                       loc='bottom',
  46.                       cellLoc='center',
  47.                       bbox=[0, -0.6, 1.0, 0.5])
  48. the_table.set_fontsize(14)
  49. the_table.scale(1.0, 1.7)  # may help
  50. # 调整table的布局
  51. # plt.subplots_adjust(left=0.2, bottom=0.1)
  52. # label和ticks的设置
  53. # minN, maxN = pltPD.values.flatten().min(), pltPD.values.flatten().max()
  54. # plt.yticks(np.arange(minN, maxN, (maxN-minN)/5), fontsize=14)
  55. plt.yticks(np.arange(0, 1.1, 0.2), fontsize=14)
  56. plt.xticks([])
  57. plt.title('Comparison between Different Models', fontsize=14)
  58. plt.show()

最终的效果如下所示:

matplotlib绘图优化–表格与柱状图结合
  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: