@[toc]
Matplotlib 基础
matplotlib 是一个 Python 的 2D 图形包。pyplot 封装了很多画图的函数。
导入相关的包:
import matplotlib.pyplot as plt
import numpy as np
matplotlib.pyplot
包含一系列类似 MATLAB 中绘图函数的相关函数。每个 matplotlib.pyplot 中的函数对当前的图像进行一些修改,例如:产生新的图像,在图像中产生新的绘图区域,在绘图区域中画线,给绘图加上标记,等等.. matplotlib.pyplot 会自动记住当前的图像和绘图区域,因此这些函数会直接作用在当前的图像上。
在实际的使用过程中,常以 plt
作为 matplotlib.pyplot 的省略。
plt.show() 函数
默认情况下,matplotlib.pyplot 不会直接显示图像,只有调用 plt.show() 函数时,图像才会显示出来。
类似 print()
plt.show() 默认是在新窗口打开一幅图像,并且提供了对图像进行操作的按钮。
plt.plot() 函数
plt.plot()函数是 matplotlib.pyplot 模块下的一个函数, 用于画图。
它可以绘制 点图
和 线图
,并且对其样式进行控制
基本用法
(1)默认参数
y轴元素是必须要指定的。x轴元素如果不指定,默认为y轴元素的索引(0、1、2、3...)。
- plt.plot (y)
plt.plot([1,2,3,4])
(2)指定x和y
- plt.plot (x,y)
plt.plot([1,2,3,4],[1,4,9,16])
(3)给x轴和y轴命名
- plt.xlabel ('名字')
- plt.ylabel ('名字')
plt.plot([1,2,3,4])
plt.xlabel('x')
plt.ylabel('y')
注意:如果名字含中文的话,需要加上一个设置:
plt.rcParams['font.sans-serif'] = ['SimHei'] # 把中文设成黑体
如果不加这句,中文就是乱码
用字符参数设置线条属性
这些参数都可以用在各种图形的绘制中。
可以用字符来指定线条的属性,即绘制图像时,线的样子。
表示颜色的字符参数:
字符 | 颜色 |
---|---|
'b' | blue,蓝色 |
'g' | green,绿色 |
'r' | red,红色 |
'c' | cyan,青色 |
'm' | magenta,品红 |
'y' | yellow,黄色 |
'k' | black,黑色 |
'w' | white,白色 |
表示类型(样子)的字符参数:
字符 | 类型 | 字符 | 类型 |
---|---|---|---|
'-' | 实线 | '--' | 虚线 |
'-.' | 虚点线 | ':' | 点线 |
'.' | 点 | ',' | 像素点 |
'^' | 上三角点 | 'v' | 下三角点 |
'<' | 左三角点 | '>' | 右三角点 |
'1' | 下三叉点 | '2' | 上三叉点 |
'3' | 左三叉点 | '4' | 右三叉点 |
'o' | 原点 | 's' | 正方点 |
'p' | 五角点 | '*' | 星形点 |
'h' | 六边形点1 | 'H' | 六边形点2 |
'+' | 加号点 | 'x' | 乘号点 |
'D' | 实心菱形点 | 'd' | 瘦菱形点 |
'_' | 横断点 |
练习:用品红虚线画图
plt.plot([1,2,3,4],[1,4,9,16],'--m')
可以看出,起始点和终点都在图像的边缘,不太好看。因此需要改变轴的显示范围,让图变好看。
显示范围
使用 axis
函数指定坐标轴的显示范围:
- plt.axis ([ xmin,xmax,ymin,ymax ])
plt.plot([1,2,3,4],[1,4,9,16],'--m')
plt.axis([0,6,0,20])
传入 Numpy 数组
之前传给 plot 的参数都是列表。实际上,向 plot 中传入 numpy 数组是更常用的做法。
PS:如果传入的是列表,matplotlib 会在内部将它转化成数组再进行处理。
t = np.arange(0,5,0.2) # 构造 numpy 数组
plt.plot(t,t,'r--') # 把numpy传给plot
传入多组数据
我们不需要使用多个 plot 函数来画多组数据,只需要将这些组合放到一个 plot 函数中去即可。
通过传入多组 (x,y,格式)
参数,使多个 plot 函数在同一张图上显示。
在一个图里面画多条线:
格式 :plt.plot(x,y,格式,x,y,格式,x,y,格式,...)
1.先构造一个 numpy 数组
t = np.arange(0,5,0.2)
2.多条线之间用逗号(,)隔开
plt.plot(t,t,'r--', t,t*t,'g*', t,t**3,'c^')
用其他参数设置线条属性
这些参数都可以用在各种图形的绘制中。
之前提到,可以用字符串指定线条的属性。事实上还可以通过 关键字
来改变线条的属性。例如: linewidth
可以改变线条的宽度,color
可以改变线条的颜色 。
x = np.linspace(-np.pi,np.pi)
y = np.sin(x)
plt.plot(x,y,linewidth = 4,color = 'c')
用 plt.plot() 的返回值来设置线条属性
plot 函数返回一个 Line2D 对象组成的列表,每个对象代表输入的一对组合,例如:
- line1,line2 为两个 Line2D
对象
line1,line2 = plt.plot (x1,y1,x2,y2)
- 返回 多个 Line2D 对象组成的
列表
lines = plt.plot (x1,y1,x2,y2,x3,y3,...)
PS :只能给对象进行属性设置;不能对列表进行属性设置!
使用返回值设置线条属性:
# line1 和 line2 就是返回值
line1,line2 = plt.plot(x,y,'r',x,y+1) # 红色line1,蓝色line2
line1.set_antialiased(False) # 关闭抗锯齿,不平滑了
PS :不能对列表进行属性设置!
lines = plt.plot(x,y,'r',x,y+1)
lines.set_antialiased(False)
会报错:
AttributeError: 'list' object has no attribute 'set_antialiased'
但可以从列表中取对象:
lines = plt.plot(x,y,'r',x,y+1)
lines[1].set_antialiased(False)
用 plt.setp() 修改线条属性
更方便的做法是使用: plt 的 setp 函数 。
line = plt.plot(x,y)
plt.setp(line,color = 'g',linewidth = 4)
子图
figure
函数会产生一个指定编号为 num(具体数字)的主图(画布) :
plt.figure(num)
如果 num = 1,即 figure(1) 时可以省略,因为默认 plt 会产生一幅图 。
PS :如果绘制多张图,编号num才有用呢,给不同图赋编号嘛。如果就画一张图,那就没必要专门设置 num了。
多个figure就是多个图。每个图都可能包含一个或多个子图。
也可以用 figsize
参数定义图片的大小:
plt.figure(figsize = (10,6))
figure图大小 :长10宽6
subplot
函数可以在 一幅图(一个figure对象/一张画布)中生成多个子图:
plt.subplot(numRows,numCols,plotNum)
注意:
如果3个参数都是一位数,那么中间的逗号(,)可以省略。因此,plt.subplot (2,1,1) 就可以简写成plt.subplot (211) 。参数意思是:图像是 2 x 1(2行1列)的,且当前选中的是两个 subplot 中的第1个。
参数:
- numRows :表示将整个绘图区域等分为numRows行
- numCols :表示将整个绘图区域等分为numCols列
- plotNum :表示当前选中要操作的区域
几行几列第几个子图
def f(t):
return np.exp(-t) * np.cos(2 * np.pi * t)
t1 = np.arange(0,5,0.1)
t2 = np.arange(0,5,0.02)
plt.figure(figsize = (10,6)) # 设置画布大小
plt.subplot(211) # 图像是2x1的,且当前选中的是两个subplot中的第1个
plt.plot(t1,f(t1),'o',t2,f(t2),'g')
plt.subplot(212) # 图像是2x1的,且当前选中的是两个subplot中的第2个
plt.plot(t2,np.cos(2*np.pi*t2),'r--')
实战练习:电影数据绘图
在了解了绘图的基础知识后,终于可以对电影数据进行可视化分析了!
前提工作:
1.导入库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
2.去除警告
import warnings
warnings.filterwarnings('ignore')
3.解决中文乱码等问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 把中文设成黑体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
4.读入数据
df = pd.read_excel(r'D:\数据分析\movie_data3.xlsx')
plt.bar() —— 柱状图的绘制
柱状图
(bar chart),是一种以长方形的长度为变量的表达图形的统计报告图,由一系列高度不等的纵向条纹表示数据分布的情况,用来比较两个或以上的价值(不同时间或不同条件),只有一个变量,通常用于较小的数据集分析。柱状图也可以横向排列,或用多维方式表达。
增添细节:
plt.title
:设置图的标题(写的这些都可加fontsize设置字体大小)plt.xlabel
:设置x轴名字plt.ylabel
:设置y轴名字plt.tick_params
(labelsize = 14) :坐标轴上字体大小plt.xticks
(rotation = 90) :把字旋转多少度(此时为90°)。x轴上的字都挤在一起了,把字竖着写好看plt.text
(数据放的x轴位置,数据放的y轴位置,放上面的数据,ha = xxx,...) :把数字显示在柱上,如果想要每个柱子都显示就得用循环。ha参数:对齐方式。plt.grid
:图上加网格线- ...还有很多,常用的有这些,其他没记的用的时候再查
补充:value_counts()
是⼀种查看表格某列中有多少个不同值的快捷方法,并计算每个不同值有在该列中有多少重复值 。
绘制每个产地的电影数量的柱状图
1.先取得数据:
data = df['产地'].value_counts()
2.再绘制图形:
x = data.index # 地区做x轴
y = data.values # 电影数量做y轴
plt.figure(figsize = (15,8)) # 先把画布大小设置好
plt.bar(x,y,color = 'c')
plt.title('各产地电影数量',fontsize = 20) # 设置图的标题(fontsize是字体大小)
plt.xlabel('产地',fontsize = 18) # x轴名字
plt.ylabel('电影数量',fontsize = 18) # y轴名字
plt.tick_params(labelsize = 14) # 坐标轴上字体大小
plt.xticks(rotation = 90) # 把字旋转多少度。x轴上的字都挤在一起了,把字竖着写
# 把数字显示在柱上(每个柱子都显示就得用循环)
for a,b in zip(x,y):
plt.text(a,b+100,b,ha = 'center',fontsize = 10)
# (数据放的x轴位置,数据放的y轴位置,放上面的数据)
# b+100解释:数据紧贴着柱不好看,就放在柱上面一点
# ha参数:水平对其方式
plt.plot() —— 曲线图的绘制
曲线图又称 折线图
,是利用曲线的升、降变化来表示被研究现象发展变化趋势
的一种图形。它在分析研究社会经济现象的发展变化、依存关系等方面具有重要作用。
依然用 plt.plot
增添细节:
plt.title
:设置图的标题(写的这些都可加fontsize设置字体大小)plt.xlabel
:设置x轴名字plt.ylabel
:设置y轴名字plt.text
:在指定位置放入文字
除了使用 text 在指定位置标上文字之外,还可以使用 plt.annotate
函数进行注释,plt.annotate
主要有两个参数:
xy
:被注释的坐标点。xytext
:注释文字的坐标位置。arrowprops
:设置箭头的样子。参数类型为字典。facecolor:内部颜色,edgecolor:边缘颜色,...
绘制1888到2015年的电影数量的折线图
1.把2016年数据剔除,只保留1888-2015年的数据
# 统计各个年份的电影数据
data = df['年代'].value_counts()
# 按年代排序
data = data.sort_index()
# 只保留1888到2015,最后的2016不要了
data = data[:-1]
2.绘制图形:
x = data.index # 年代做x轴
y = data.values # 电影数量做y轴
plt.figure(figsize = (15,8)) # 先把画布大小设置好
plt.plot(x,y,color = 'c')
plt.title('各年代电影数量',fontsize = 20) # 设置图的标题(fontsize是字体大小)
plt.xlabel('年代',fontsize = 18) # x轴名字
plt.ylabel('电影数量',fontsize = 18) # y轴名字
plt.tick_params(labelsize = 14) # 坐标轴上字体大小
# 把每隔10年的数据写在图上
for a,b in zip(x[::10],y[::10]):
plt.text(a,b+50,b,ha = 'center',fontsize = 10)
# (数据放的x轴位置,数据放的y轴位置,放上面的数据)
# b+100解释:数据紧贴着柱不好看,就放在柱上面一点
# ha参数:水平对其方式
# 加注释 # arrowprops要用字典传参
plt.annotate('2012年达到最大值',xy = (2012,data[2012]),xytext = (2025,2100),arrowprops = {'facecolor':'yellow','edgecolor':'magenta'})
# 在折线图陡峭的地方加一段话
plt.text(1980,1000,'电影数量开始快速增长',fontsize = 13)
从上图可以看出,电影数量是逐年增加的,增长的趋势在2000年后变得飞快。
plt.pie() —— 饼图的绘制
饼图
常用于统计学模块。2D饼图为圆形。适用于分类不多的数据。
仅排列在工作表的一列或一行中的数据可以绘制到饼图中。饼图显示一个数据系列中各项的大小与各项总和的比例。饼图中的数据点显示为整个饼图的百分比。
PS :
数据系列:
在图表中绘制的相关数据点,这些数据源自数据表的行或列。图表中的每个数据系列具有唯一的颜色或图案,并且在图表的图例中表示。可以在图表中绘制一个或多个数据系列。饼图只有一个数据系列。
数据点:
在图表中绘制的单个值,这些值由条形、柱形、折线、饼图、或圆环图的扇面、圆点和其他被称为数据标记的图形表示。相同颜色的数据标记组成一个数据系列。
plt.pie
饼图用的函数:
plt.pie(x, explode = None, labels = None, colors = None, autopct = None, pctdistance = 0.6,shadow = False, labeldistance = 1.1, startangle = None, radius = None)
参数:
x
:数组。表示每一块的比例,如果 sum(x) > 1 会使 sum(x) 归一化。explode
:数组。每一块离开中心的距离。labels
:列表。饼图外侧,每一块饼块显示的说明文字。color
:数组。用来标注每块饼图的matplotlib颜色参数序列。默认为为None,将使用当前活动环的颜色。autopct
:控制饼图内百分比设置,可以使用format字符串或format function。pctdistance
:指定 autopct 的位置刻度。shadow
:在饼图下面画个阴影。labeldistance
:绘制位置。相对于半径的比例,如果 <1 则绘制在饼图内侧。startangle
:起始绘制角度,默认图是从x轴正方向逆时针画起。如果设定 =90,则从y轴正方向画起。radius
:控制饼图的半径。
返回值:
- 如果
没有
设置autopct
:返回(patches,texts) - 如果
设置
了autopct
:返回(patches,texts,autotexts)
根据电影时长绘制饼图
1.把数据先搞出来
data = pd.cut(df['时长'],[0,60,90,110,1000])
data = data.value_counts()
2.绘制图形:
x = data.index
y = data.values
# y = data.values/sum(data.values) 饼图得用百分比表示。但这一步可有可无,数据会自动转化位百分比
plt.figure(figsize = (10,10)) # 注意:饼图的长宽要一致!!!
plt.title('电影时长占比',fontsize = 15)
# 通过函数返回值定义图像的字体 l_text:饼图外部的文字 p_text:饼图内部的文字
patches,l_text,p_text = plt.pie(y,labels = x,autopct = '%.1f %%',colors = 'bcmy',startangle = 90) # 这里注意是 colors
# f表示浮点数,.1表示1位。前后都必须加 %,有百分号%才意味着在进行格式的说明。倒数第二个百分号意味着是百分比数
# startangle 让图从y轴正方向开始画
# 利用返回值,设置饼图内部的字体
for i in p_text:
i.set_size(15) # 内部字体大小
i.set_color('w') # 内部字体颜色
for i in l_text:
i.set_size(18) # 外部字体大小
i.set_color('r') # 外部字体颜色
plt.legend() # 加上图例
plt.hist() —— 直方图的绘制
直方图
又称质量分布图。是一种统计报告图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。一般用横轴表示数据类型,纵轴表示分布情况。
直方图是数值数据分布的精确图形表示。是一个连续变量(定量变量)的概率分布的估计。是一种条形图。
构造直方图,第一步是将值的范围分段,即将整个值的范围分成一系列间隔。第二部是计算每个间隔中有多少值。这些值通常被指定为连续的,不重叠的变量间隔。间隔必须相邻,并且通常是相等的大小(但不是必须的)。
直方图也可以被归一化以显示 “相对” 频率。归一化之后,它显示了属于几个类别中的每个案例的比例,其高度等于1.
参数:
hist 的参数非常多,但常用的就这几个,只有第一个是必须的,后面都可选填。
arr
:需要计算直方图的一维数组。如果是多维数组,可以先进行扁平化再作图。必填参数!bins
:直方图的柱数,默认为10。normed
:是否将得到的直方图向量归一化。默认为0。facecolor
:直方图颜色。edgecolor
:直方图边框颜色。alpha
:透明度。取值在 0-1 之间。histtype
:直方图类型,可选项有:bar,barstacked,stepstepfilled 。
返回值:
- n :直方图向量,是否归一化由参数 normed 设定。
- bins :返回各个bin的区间范围。
- patches :返回每个bin里面包含的数据,是一个列表。
根据电影评分绘制频率分布直方图
plt.figure(figsize = (10,6))
plt.hist(df['评分'],bins = 20,edgecolor = 'k',alpha = 0.6)
plt.title('电影评分直方图',fontsize = 20)
plt.xlabel('评分',fontsize = 18) # x轴名字
plt.ylabel('电影数量',fontsize = 18) # y轴名字
plt.tick_params(labelsize = 14) # 坐标轴上字体大小
作业
(1)画出 y = x² + 2x + 1 在区间 [-1,3] 的函数图像
x = np.linspace(-1,3,50)
y = x**2 + 2*x + 1
plt.figure(figsize = (10,6))
plt.plot(x,y)
plt.title('二次函数',fontsize = 20)
plt.xlabel('x轴',fontsize = 18)
plt.ylabel('y轴',fontsize = 18)
plt.tick_params(labelsize = 15) # 坐标轴上字体大小
(2)在同一张图中创建两个子图,分别画出 sin(x) 和 cos(x) 在 [-3.14,3.14] 上的函数图像。设置线条宽度为2.5
x = np.linspace(-3.14,3.14,50)
y1 = np.sin(x)
y2 = np.cos(x)
plt.figure(figsize = (18,6))
plt.subplot(1,2,1)
plt.plot(x,y1,linewidth = 2.5)
plt.title('sin(x)',fontsize = 20)
plt.xlabel('x轴',fontsize = 18)
plt.ylabel('y轴',fontsize = 18)
plt.tick_params(labelsize = 15) # 坐标轴上字体大小
plt.subplot(1,2,2)
plt.plot(x,y2,linewidth = 2.5)
plt.title('cos(x)',fontsize = 20)
plt.xlabel('x轴',fontsize = 18)
plt.ylabel('y轴',fontsize = 18)
plt.tick_params(labelsize = 15) # 坐标轴上字体大小
(3)读取上次作业保存的酒店数据,画出每个地区酒店数量的柱状图,柱状颜色为红色
df = pd.read_excel(r'D:\数据分析\酒店数据2.xlsx')
data = df.地区.value_counts()
plt.figure(figsize = (18,6))
plt.bar(data.index,data.values,color = 'r')
plt.title('各地区酒店数量',fontsize = 20)
plt.xlabel('地区',fontsize = 18)
plt.ylabel('酒店数量',fontsize = 18)
plt.tick_params(labelsize = 15) # 坐标轴上字体大小
(4)画出每个地区酒店数量的曲线图
df = pd.read_excel(r'D:\数据分析\酒店数据2.xlsx')
data = df.地区.value_counts()
plt.figure(figsize = (18,6))
plt.plot(data.index,data.values)
plt.title('各地区酒店数量',fontsize = 20)
plt.xlabel('地区',fontsize = 18)
plt.ylabel('酒店数量',fontsize = 18)
plt.tick_params(labelsize = 15) # 坐标轴上字体大小
(5)画出各个价格等级占比的饼图
data = df.价格等级.value_counts()
plt.figure(figsize = (10,10))
patches,l_text,p_text = plt.pie(data.values,labels = data.index,autopct = '%.1f %%',startangle = 90)
plt.title('价格等级占比',fontsize = 20)
# 利用返回值,设置饼图内部的字体
for i in p_text:
i.set_size(15) # 内部字体大小
i.set_color('w') # 内部字体颜色
for i in l_text:
i.set_size(18) # 外部字体大小
i.set_color('k') # 外部字体颜色
plt.legend() # 加上图例
(6)画出酒店评分的直方图
plt.figure(figsize = (10,6))
plt.hist(df['评分'],bins = 20,edgecolor = 'k',alpha = 0.6)
plt.title('酒店评分直方图',fontsize = 20)
plt.xlabel('评分',fontsize = 18) # x轴名字
plt.ylabel('酒店数量',fontsize = 18) # y轴名字
plt.tick_params(labelsize = 14) # 坐标轴上字体大小
(7)画出每个类型酒店评分均值的曲线图(按照评分均值从小到大排序),并标记出全部酒店评分均值所在的点
group = df['评分'].groupby(df['类型']).mean() # 以类型分组求评分均值
group = group.sort_values() # 均值数据升序排列
total = group.values.mean() # 全部酒店的评分均值
plt.figure(figsize = (18,6))
plt.plot(group.index,group.values)
plt.title('各类型酒店评分均值',fontsize = 20)
plt.xlabel('类型',fontsize = 18)
plt.ylabel('酒店评分均值',fontsize = 18)
plt.tick_params(labelsize = 15) # 坐标轴上字体大小
plt.xticks(rotation = 90) # 把x轴字旋转90度
plt.annotate('全部酒店评分均值',xy = (7.2,4.4),xytext = (3.9,4.5),arrowprops = {'facecolor':'yellow','edgecolor':'magenta'},fontsize = 15)
# xy和 xytest的坐标纯属硬凑,只是为了满足题目条件
# 因为 x轴坐标是离散的,且是文字,不知道如何精准定位坐标
# 以后想明白了再回来改