matplotlib柱状图学习笔记
- 柱状图也是大家常用的一个绘图方式,使用频率十分的高,由于其形象直观,非常适合作为各种高大上的展示,而且matplotlib中柱状图功能也很成熟,随着画图顺序我一点点的记录:
- 首先仍然是
from matplotlib import pyplot as plt
,导入matplotlib - 然后传入x,y的坐标;坐标可以直接在代码中给出,也可以读取文件,推荐用pandas读取,方便快捷,这里不讲pandas。还是采用随机数进行画图吧。来四行数据;
import random
x_tickets = ['Fe_1', "Fe_2", "Fe_3", "Fe_4"] # x
y_tickets_1 = [random.uniform(10, 50) for _ in range(len(x_tickets))] # y1
y_tickets_2 = [random.uniform(10, 50) for _ in range(len(x_tickets))] # y2
y_tickets_3 = [random.uniform(10, 50) for _ in range(len(x_tickets))] # y3
y_tickets_4 = [random.uniform(10, 50) for _ in range(len(x_tickets))] # y4
- 画柱状图的方法是·plt.bar 与plt.barh, 其中barh是水平的柱状图,而bar是常规竖直的柱状图,其参数基本一模一样(使用barh注意的是把width换成height,另外注意x,y坐标轴与标签的选择)。我们按照上篇博客一样https://blog.csdn.net/weixin_44521703/article/details/98480767,加上标签,标题,字体与图例文字, 加入代码:
from matplotlib.font_manager import FontProperties
plt.bar(x_indexes, y_tickets_1, width=0.2, label="y_tickets_1")
plt.bar(x_indexes, y_tickets_2, width=0.2, label="y_tickets_2")
plt.bar(x_indexes, y_tickets_3, width=0.2, label="y_tickets_3")
plt.bar(x_indexes, y_tickets_4, width=0.2, label="y_tickets_4")
Arial = FontProperties(fname='C:\Windows\Fonts\Arial.ttf')
plt.title('The performance of different catalysts',fontproperties=Arial,fontsize=20) # title of whole picture
plt.xlabel('Catalysts',fontproperties=Arial,fontsize=14) # title of x axis
plt.ylabel('Productivity (%)',fontproperties=Arial,fontsize=14) # title of y axis
plt.ylim(0,80)
plt.legend(loc='upper left', fontsize=10, frameon=False) # show the legend
plt.tight_layout() # tight lay out
plt.show()
发现没,有几个问题:
-
柱状图都重叠在了一起;并且因为重叠,导致前面的数据如果比后面的小的话,将会被覆盖,如第二柱子处,只能看到两种颜色;
-
横坐标变成了数字0-3,但是我们想要的是
x_tickets = ['Fe_1', "Fe_2", "Fe_3", "Fe_4"] # x
,我们一个一个的来解决; -
针对第一个问题,实际上是新学习时最容易遇到的问题,处理方法实际十分简单就是将每个柱子左右挪一挪就OK了,那挪的话,实际上就是挪的x坐标位置,相当于给一个偏移量。有两种方法:
(1)一是使用常规的方法,注意到现在x轴坐标是0-3,因此可以先从此着手,先构建个列表,然后每个柱状图给个位移,为了方便,先给每个柱子设定一个宽度,比如width = 0.15;
width = 0.15
x_indexes = [i for i in range(len(x_tickets))]
lt.bar(list(map(lambda x: x-width*1.5, x_indexes)), y_tickets_1, width=width, label="y_tickets_1")
plt.bar(list(map(lambda x: x-width*0.5, x_indexes)), y_tickets_2, width=width, label="y_tickets_2")
plt.bar(list(map(lambda x: x+width*0.5, x_indexes)), y_tickets_3, width=width, label="y_tickets_3")
plt.bar(list(map(lambda x: x+width*1.5, x_indexes)), y_tickets_4, width=width, label="y_tickets_4")
这样出来的图是不是就比较正常了?
(2) 二是针对列表操作,最简单的就是使用numpy了。numpy可以十分方便的实现数组之间的加减运算。我们同样的思路。图是不是也就出来了?
import numpy as np
x_indexes = np.arange(len(x_tickets)) # 相当于创建了一个list, 内容为[0,1,2,3] ,类型为 ndarray
width = 0.15
plt.bar(x_indexes - width * 1.5, y_tickets_1, width=width, label="y_tickets_1")
plt.bar(x_indexes - width * 0.5, y_tickets_2, width=width, label="y_tickets_2")
plt.bar(x_indexes + width * 0.5, y_tickets_3, width=width, label="y_tickets_3")
plt.bar(x_indexes + width * 1.5, y_tickets_4, width=width, label="y_tickets_4")
- 接下来就该解决x轴坐标了,实际上很简单,我们让x坐标值依旧是0,1,2,3,但是,让其显示的不是值,而是标签,可以加上如下一行代码并执行,以及我们可以改一改:
plt.xticks(ticks= x_indexes, labels= x_tickets) # redefine the label
- 如果要加入颜色等,可以在plt.bar语句中加入如
color = 'black'
或者color='#444444'
这样形式的语句,就可以自定义颜色了。 - 最后,matplotlib中有很多可选的风格模板直接应用,查看可用风格可用
plt.style.available
语句,结果是: ['bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn-bright', 'seaborn-colorblind', 'seaborn-dark-palette', 'seaborn-dark', 'seaborn-darkgrid', 'seaborn-deep', 'seaborn-muted', 'seaborn-notebook', 'seaborn-paper', 'seaborn-pastel', 'seaborn-poster', 'seaborn-talk', 'seaborn-ticks', 'seaborn-white', 'seaborn-whitegrid', 'seaborn', 'Solarize_Light2', 'tableau-colorblind10', '_classic_test']
- 使用这些风格使用语句
plt.style.use('ggplot')
- 全部代码如下:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@File : Fig2A.py.py
@Time : 2019/8/5 9:19
@Author : Sound_of_Silence
"""
from matplotlib import pyplot as plt
import random
import numpy as np
plt.style.use('ggplot')
# plt.xkcd() # 比较好玩的风格
x_tickets = ['Fe_1', "Fe_2", "Fe_3", "Fe_4"] # x
y_tickets_1 = [random.randint(10, 50) for _ in range(len(x_tickets))] # y1
y_tickets_2 = [random.randint(10, 50) for _ in range(len(x_tickets))] # y2
y_tickets_3 = [random.randint(10, 50) for _ in range(len(x_tickets))] # y3
y_tickets_4 = [random.randint(10, 50) for _ in range(len(x_tickets))] # y4
x_indexes = np.arange(len(x_tickets))
width_1 = 0.15
plt.bar(x_indexes - width * 1.5, y_tickets_1, width=width, label="y_tickets_1")
plt.bar(x_indexes - width * 0.5, y_tickets_2, width=width, label="y_tickets_2")
plt.bar(x_indexes + width * 0.5, y_tickets_3, width=width, label="y_tickets_3")
plt.bar(x_indexes + width * 1.5, y_tickets_4, width=width, label="y_tickets_4")
plt.title('The performance of different catalysts', fontsize=18) # title of whole picture
plt.xlabel('Catalysts', fontsize=18) # title of x axis
plt.ylabel('Productivity (%)', fontsize=18) # title of y axis
plt.xticks(ticks=x_indexes, labels=x_tickets, fontsize=14) # redefine the label
plt.yticks(fontsize=14)
plt.ylim(0, 80)
plt.legend(loc='upper left', fontsize=10, frameon=False) # show the legend
plt.tight_layout() # tight lay out
plt.rcParams['savefig.dpi'] = 600
plt.show()
或者用xkcd(),看起来像漫画或者手绘风格: