不同图形的绘制
柱状图:
- 柱状图是一种用矩形柱来表示数据分类的图表。
- 柱状图可以垂直绘制,也可以水平绘制。
- 它的高度与其所表示的数值成正比关系。
- 柱状图显示了不同类别之间的比较关系,图表的水平轴 X 指定被比较的类别,垂直轴 Y 则表示具体的类别值
1.柱状图的绘制
matplotlib.pyplot.bar(x, height, width: float = 0.8, bottom = None, *,
align: str = ‘center’, data = None, **kwargs)
- x 表示x坐标,数据类型为float类型,一般为np.arange()生成的固定步长列表
- height 表示柱状图的高度,也就是y坐标值,数据类型为float类型,一般为一个列表,包含生成柱状图的所有y值
- width 表示柱状图的宽度,取值在0~1之间,默认值为0.8
- bottom 柱状图的起始位置,也就是y轴的起始坐标,默认值为None
- align 柱状图的中心位置,“center”,"lege"边缘,默认值为’center’
- color 柱状图颜色,默认为蓝色
- alpha 透明度,取值在0~1之间,默认值为1
- label 标签,设置后需要调用plt.legend()生成
- edgecolor 边框颜色 (ec)
- linewidth 边框宽度,浮点数或类数组,默认为None (lw)
- tick_label:柱子的刻度标签,字符串或字符串列表,默认值为None。
- linestyle :线条样式 (ls)
1. 基本的柱状图
import matplotlib.pyplot as plt
# x轴数据
x = range(5)
# y轴数据
data = [5, 20, 15, 25, 10]
# 设置图形标题
plt.title("基本柱状图")
# 绘制网格
plt.grid(ls="--", alpha=0.5)
plt.rcParams['font.sans-serif'] = ["FangSong"]
# bar绘制图形,x 表示x坐标 data为表示柱状图的高度
plt.bar(x, data)
- bottom参数:柱状图的起始位置,也就是y轴的起始坐标,默认值为None
import matplotlib.pyplot as plt
# x轴数据
x = range(5)
# y轴数据
data = [5, 20, 15, 25, 10]
# 设置图形标题:
plt.title("基本柱状图")
# 绘制网格
plt.grid(ls="--", alpha=0.5)
# bar绘制图形,x 表示x坐标 data为表示柱状图的高度
plt.bar(x, data, bottom=[10, 20, 5, 0, 10])
# 注意data = [5, 20, 15, 25, 10] ----对应的bottom-->[10, 20, 5, 0, 10]
'''
--- a.形状要一致
--- b.每个图形y轴的起始位置
'''
- 柱状图颜色
plt.bar(x, data ,facecolor="green")
#plt.bar(x, data ,color="green")
'''
facecolor和color设置单个颜色时使用方式一样
color可以设置多个颜色值,facecolor不可以
'''
plt.bar(x, data ,color=['r', 'g', 'b'])
- 描边 -相关的关键字参数为:
- edgecolor 或 ec
- linestyle 或 ls
- linewidth 或 lw
plt.bar(range(len(data)), data, ec='r', ls='--', lw=2)
2.同位置多柱状图
同一 x 轴位置绘制多个柱状图,主要通过调整柱状图的宽度和每个柱状图x轴的 起始位置
分析:
- 本实例需要对x轴进行计算,因此需要将x轴转数值
- 确定同一x轴中,每个柱状图x轴的起始位置。
- 需要设置图形的宽度
- 图形2的起始位置=图形2起始位置+图形的宽度
- 图形3的起始位置=图形3起始位置+2倍图形的宽度
- 需要给每个柱状图循环显示文本内容
- 显示图例
from matplotlib import pyplot as plt
import numpy as np
# 设置基本属性.....
# ........... 省略..........
# 国家
countries = ['挪威', '德国', '中国', '美国', '瑞典']
# 金牌个数
gold_medal = [16, 12, 9, 8, 8]
# 银牌个数
silver_medal = [8, 10, 4, 10, 5]
# 铜牌个数
bronze_medal = [13, 5, 2, 7, 5]
# 1.将x轴转换为数值
x_int = np.arange(len(countries))
# 2.设置图形的宽度
width = 0.2
# 确定x起始位置
gold_x = x_int # 金牌起始位置
silver_x = x_int+width # 银牌的起始位置
bronze_x = x_int + 2*width # 铜牌的起始位置
# 分别绘制图形
plt.bar(gold_x, gold_medal, width=width,color="gold", label="金牌") # 金牌图形
plt.bar(silver_x, silver_medal, width=width, color="silver",label="银牌") # 银牌图形
plt.bar(bronze_x, bronze_medal, width=width, color="saddlebrown",label="铜牌") # 铜牌图形
# 将x轴的坐标变回来
# plt.xticks(x_int,labels=countries)
# 移动x标记的位置,再替换内容
plt.xticks(x_int + width,labels=countries)
#-----------显示高度文本----------------
# # 金牌
# for x,y in zip(gold_x,gold_medal):
# plt.text(x,y,y,va="bottom",ha="center",fontsize=8)
# # 银牌牌
# for x,y in zip(silver_x, silver_medal):
# plt.text(x,y,y,va="bottom",ha="center",fontsize=8)
# # 铜牌
# for x,y in zip(bronze_x, bronze_medal):
# plt.text(x,y,y,va="bottom",ha="center",fontsize=8)
# 金牌 # 银牌 # 铜牌
for i in range(len(countries)):
# 金牌
plt.text(gold_x[i],gold_medal[i], gold_medal[i],va="bottom",ha="center",fontsize=8)
# 银牌
plt.text(silver_x[i],silver_medal[i], gold_medal[i],va="bottom",ha="center",fontsize=8)
# 铜牌
plt.text(bronze_x[i],bronze_medal[i], gold_medal[i],va="bottom",ha="center",fontsize=8)
# 显示图例
plt.legend()
其他知识点:在 Matplotlib 中旋转 X 轴刻度标签文本
- plt.xticks(rotation= ) 旋转 Xticks 标签文本
- fig.autofmt_xdate(rotation= ) 旋转 Xticks 标签文本
- ax.set_xticklabels(xlabels, rotation= ) 旋转 Xticks 标签文本
- plt.setp(ax.get_xticklabels(), rotation=) 旋转 Xticks 标签文本
- ax.tick_params(axis=‘x’, labelrotation= ) 旋转 Xticks 标签文本
from matplotlib import pyplot as plt
import numpy as np
# 设置基本属性.....
# ........... 省略..........
# 国家
countries = ['挪威', '德国', '中国', '美国', '瑞典']
# 金牌个数
gold_medal = [16, 12, 9, 8, 8]
# 银牌个数
silver_medal = [8, 10, 4, 10, 5]
# 铜牌个数
bronze_medal = [13, 5, 2, 7, 5]
# 设置画布
fig = plt.figure(figsize=(6,4),dpi=150)
# 一个画布分为2行3列,定位第一个
ax1 = fig.add_subplot(234)
ax1.set_title("金牌榜")
# 旋转x标签
ax1.tick_params(axis="x",rotation=45)
# 金牌榜
ax1.bar(countries, gold_medal, color="gold")
# 一个画布分为2行3列,定位第二个
ax2 = fig.add_subplot(235)
ax2.set_title("银牌榜")
# 旋转x标签
ax2.tick_params(axis="x",rotation=45)
# 银牌榜
ax2.bar(countries, silver_medal, color="silver")
# 一个画布分为2行3列,定位第二个
ax3 = fig.add_subplot(236)
ax3.set_title("铜牌榜")
# 旋转x标签
ax3.tick_params(axis="x",rotation=45)
# 铜牌榜
ax3.bar(countries, bronze_medal, color="#A0522D")
# ================绘制总图:绘制2行一列,移动到第一行======
ax = fig.add_subplot(211)
# 1.将x轴转换为数值
x_int = np.arange(len(countries))
# 2.设置图形的宽度
width = 0.2
# 确定x起始位置
gold_x = x_int # 金牌起始位置
silver_x = x_int+width # 银牌的起始位置
bronze_x = x_int + 2*width # 铜牌的起始位置
# 分别绘制图形
ax.bar(gold_x, gold_medal, width=width,color="gold", label="金牌") # 金牌图形
ax.bar(silver_x, silver_medal, width=width, color="silver",label="银牌") # 银牌图形
ax.bar(bronze_x, bronze_medal, width=width, color="saddlebrown",label="铜牌") # 铜牌图形
# 将x轴的坐标变回来
# plt.xticks(x_int,labels=countries)
# 移动x标记的位置,再替换内容
ax.set_xticks(x_int + width)
ax.set_xticklabels(countries )
#-----------显示高度文本----------------
# 金牌 # 银牌 # 铜牌
for i in range(len(countries)):
# 金牌
ax.text(gold_x[i],gold_medal[i], gold_medal[i],va="bottom",ha="center",fontsize=8)
# 银牌
ax.text(silver_x[i],silver_medal[i], gold_medal[i],va="bottom",ha="center",fontsize=8)
# 铜牌
ax.text(bronze_x[i],bronze_medal[i], gold_medal[i],va="bottom",ha="center",fontsize=8)
# 显示图例
ax.legend(fontsize=6 )
# 处理标题覆盖
plt.tight_layout()
2.堆叠柱状图
所谓堆叠柱状图就是将不同数组别的柱状图堆叠在一起,堆叠后的柱状图高度显示了两者相加的结果值。 如图:
countries = ['挪威', '德国', '中国', '美国', '瑞典']
# 金牌个数
gold_medal = np.array([16, 12, 9, 8, 8])
# 银牌个数
silver_medal = np.array([8, 10, 4, 10, 5])
# 铜牌个数
bronze_medal = np.array([13, 5, 2, 7, 5])
# 绘制堆叠图
# 宽度
width = 0.3
# 绘制金牌
plt.bar(countries, gold_medal, color='gold', label='金牌',
bottom=silver_medal + bronze_medal,width=width)
# 绘制银牌
plt.bar(countries, silver_medal, color='silver', label='银牌', bottom=bronze_medal,width=width)
# 绘制铜牌
plt.bar(countries, bronze_medal, color='#A0522D', label='铜牌',width=width)
# 设置坐标轴
plt.ylabel('奖牌数')
# 设置图例
plt.legend(loc='upper right')
# 设置文本值
for i in range(len(countries)):
max_y = bronze_medal[i]+silver_medal[i]+gold_medal[i]
plt.text(countries[i], max_y, max_y, va="bottom", ha="center")
3.水平条形图
调用 Matplotlib 的 barh() 函数可以生成水平柱状图。
- barh() 函数的用法与 bar() 函数的用法基本一样,只是在调用 barh() 函数时使用 y参数传入 Y 轴数据,使用 width 参数传入代表条柱宽度的数据。
plt.barh(y, width, height=0.8, left=None, *, align='center', **kwargs)
countries = ['挪威', '德国', '中国', '美国', '瑞典']
# 金牌个数
gold_medal = np.array([16, 12, 9, 8, 8])
# y轴为国家,宽度为奖牌数
plt.barh(countries, width=gold_medal)
三天中3部电影的票房变化
movie = [‘新蝙蝠侠’, ‘狙击手’, ‘奇迹笨小孩’]
real_day1 = [4053, 2548, 1543]
real_day2 = [7840, 4013, 2421]
real_day3 = [8080, 3673, 1342]
# 由于牵扯计算,因此将数据转numpy数组
movie = ['新蝙蝠侠', '狙击手', '奇迹笨小孩']
# 第一天
real_day1 = np.array( [4053, 2548, 1543])
# 第二天
real_day2 = np.array([7840, 4013, 2421])
# 第三天
real_day3 = np.array([8080, 3673, 1342])
# ================确定距离左侧========
left_day2 = real_day1 # 第二天距离左侧的为第一天的数值
left_day3 = real_day1 + real_day2 # 第三天距离左侧为 第一天+第二天的数据
# 设置线条高度
height = 0.2
# 绘制图形:
plt.barh(movie, real_day1, height=height) # 第一天图形
plt.barh(movie, real_day2, left=left_day2, height=height) # 第二天图形
plt.barh(movie, real_day3, left=left_day3, height=height) # 第三天图形
# 设置数值文本: 计算宽度值和y轴为值
sum_data = real_day1 + real_day2 +real_day3
# horizontalalignment控制文本的x位置参数表示文本边界框的左边,中间或右边。---->ha
# verticalalignment控制文本的y位置参数表示文本边界框的底部,中心或顶部 ---- va
for i in range(len(movie)):
plt.text(sum_data[i], movie[i], sum_data[i],va="center" , ha="left")
plt.xlim(0,sum_data.max()+2000)
绘制同位置多柱状图
# 由于牵扯计算,因此将数据转numpy数组
movie = ['新蝙蝠侠', '狙击手', '奇迹笨小孩']
# 第一天
real_day1 = np.array( [4053, 2548, 1543])
# 第二天
real_day2 = np.array([7840, 4013, 2421])
# 第三天
real_day3 = np.array([8080, 3673, 1342])
# =================1.y轴转换为数值型======
num_y = np.arange(len(movie))
# ================2.需要设置同图形的高度========
height = 0.2
# ================3.计算每个图形高度的起始位置 ==========
movie1_start_y = num_y # 第一个电影不变
movie2_start_y = num_y + height # 第二个电影加上1倍的height
movie3_start_y = num_y + 2 * height # 第三个电影加上2倍的height
# ================4.绘制图形 ===================
plt.barh(movie1_start_y, real_day1, height=height) # 第一天图形
plt.barh(movie2_start_y, real_day2, height=height) # 第二天图形
plt.barh(movie3_start_y, real_day3, height=height) # 第三天图形
# 设置数值文本: 计算宽度值和y轴为值
# ============5.替换y轴数据
plt.yticks(num_y + height, movie)
直方图 plt.hist()
直方图(Histogram),又称质量分布图,它是一种条形图的一种,由一系列高度不等的纵向线段来表示数据分布的情况。 直方图的横轴表示数据类型,纵轴表示分布情况。
首先,我们需要了解柱状图和直方图的区别。直方图用于概率分布,它显示了一组数值序列在给定的数值范围内出现的概率;而柱状图则用于展示各个类别的频数。
柱状图 | 直方图 |
---|---|
柱状图一般用于描述离散型分类数据的对比 | 直方图一般用于描述连续型数据的分布关系 |
每根柱子宽度固定,柱子之间会有间距 | 每根柱子宽度可以不一样,且一般没有间距 |
横轴变量可以任意排序 | 横轴变量有一定顺序规则 |
将统计值的范围分段,即将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 直方图也可以被归一化以显示“相对”频率。 然后,它显示了属于几个类别中的每个类别的占比,其高度总和等于1。
plt.hist(x, bins=None, range=None, density=None, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, normed=None, *, data=None, **kwargs)
- x: 作直方图所要用的数据,必须是一维数组;多维数组可以先进行扁平化再作图;必选参数;
- bins: 直方图的柱数,即要分的组数,默认为10;
- weights:与x形状相同的权重数组;将x中的每个元素乘以对应权重值再计数;如果normed或density取值为True,则会对权重进行归一化处理。这个参数可用于绘制已合并的数据的直方图;
- density:布尔,可选。如果"True",返回元组的第一个元素将会将计数标准化以形成一个概率密度,也就是说,直方图下的面积(或积分)总和为1。这是通过将计数除以数字的数量来实现的观察乘以箱子的宽度而不是除以总数数量的观察。如果叠加也是“真实”的,那么柱状图被规范化为1。(替代normed)
- bottom:数组,标量值或None;每个柱子底部相对于y=0的位置。如果是标量值,则每个柱子相对于y=0向上/向下的偏移量相同。如果是数组,则根据数组元素取值移动对应的柱子;即直方图上下便宜距离;
- histtype:{‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’};'bar’是传统的条形直方图;'barstacked’是堆叠的条形直方图;'step’是未填充的条形直方图,只有外边框;‘stepfilled’是有填充的直方图;当histtype取值为’step’或’stepfilled’,rwidth设置失效,即不能指定柱子之间的间隔,默认连接在一起;
- align:{‘left’, ‘mid’, ‘right’};‘left’:柱子的中心位于bins的左边缘;‘mid’:柱子位于bins左右边缘之间;‘right’:柱子的中心位于bins的右边缘;
- color:具体颜色,数组(元素为颜色)或None。
- label:字符串(序列)或None;有多个数据集时,用label参数做标注区分;
- normed: 是否将得到的直方图向量归一化,即显示占比,默认为0,不归一化;不推荐使用,建议改用density参数;
- edgecolor: 直方图边框颜色;
- alpha: 透明度;
# 使用numpy随机生成300个随机数据
x_value = np.random.randint(140,180,300)
plt.hist(x_value, bins=10, edgecolor='white')
#plt.hist(x_value, bins=20, edgecolor='white')
plt.title("数据统计")
plt.xlabel("身高")
plt.ylabel("比率")
返回值
- n : 数组或数组列表
- 直方图的值
- bins : 数组
- 返回各个bin的区间范围
- patches : 列表的列表或列表 -返回每个bin里面包含的数据,是一个list
num,bins_limit,patches = plt.hist(x_value, bins=10, edgecolor='white')
plt.grid(ls="--")
# 绘制直方图返回元组,元组中有三个元素
num,bins_limit,patches = plt.hist(x_value, bins=10, edgecolor='white')
print("n 是分组区间对应的频率:",num,end="\n\n")
print("bins_limit 是分组时的分隔值:",bins_limit,end="\n\n")
print("patches 指的是是直方图中列表对象",type(patches),end="\n\n")
#plt.xticks(bins_limit)
plt.show()
x_limit_value = []
height_value = []
for item in patches:
print(item)
x_limit_value.append(item.get_x())
height_value.append(item.get_height())
print(x_limit_value)
print(height_value)
- xy:xy位置(x取值bins_limits 是分组时的分隔值,y取值都是0开始)
- width :宽度为各个bin的区间范围(bins_limits 是分组时的分隔值)
- height :高度也就是密度值(n 是分组区间对应的频率)
- angle:角度
添加折线直方图
在直方图中,我们也可以加一个折线图,辅助我们查看数据变化情况
- 首先通过pyplot.subplots()创建Axes对象
- 通过Axes对象调用hist()方法绘制直方图,返回折线图所需要的下x,y数据
- 然后Axes对象调用plot()绘制折线图
- 我们对第一节代码进行改造一下
# 创建一个画布
fig, ax = plt.subplots()
# 绘制直方图
num,bins_limit,patches = ax.hist(x_value, bins=10, edgecolor='white')
# 注意num返回的个数是10,bins_limit返回的个数为11,需要截取
print(bins_limit[:-1])
# 曲线图
ax.plot(bins_limit[:10], num, '--',marker="o")
#ax.set_xticks(bins_limit)
# 需要单独设置x轴的旋转
plt.xticks(bins_limit,rotation=45)
不等距分组
面的直方图都是等距的,但有时我们需要得到不等距的直方图,这个时候只需要确定分组上下限,并指定 histtype=“bar” 就可以
fig, ax = plt.subplots()
x = np.random.normal(100,20,100) # 均值和标准差
bins = [50, 60, 70, 90, 100,110, 140, 150]
ax.hist(x, bins, color="g",rwidth=0.5)
ax.set_title('不等距分组')
plt.show()
多类型直方图
我们在使用直方图查查看数据的频率时,有时候会查看多种类型数据出现的频率。
- 这时候我们可以以列表的形式传入多种数据给hist()方法的x数据
# 指定分组个数
n_bins=10
fig,ax=plt.subplots(figsize=(8,5))
# 分别生成10000 , 5000 , 2000 个值
x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
# 实际绘图代码与单类型直方图差异不大,只是增加了一个图例项
# 在 ax.hist 函数中先指定图例 label 名称
ax.hist(x_multi, n_bins, histtype='bar',label=list("ABC"))
ax.set_title('多类型直方图')
# 通过 ax.legend 函数来添加图例
ax.legend()
堆叠直方图
我们有时候会对吧同样数据范围情况下,对比两组不同对象群体收集的数据差异
- 直方图属性data:以列表的形式传入两组数据
- 设置直方图stacked:为True,允许数据覆盖
#准备两组数据:
x_value = np.random.randint(140,180,200)
x2_value = np.random.randint(140,180,200)
plt.hist([x_value,x2_value],bins=10, stacked=True)
饼状图 pie()
饼状图用来显示一个数据系列,具体来说,饼状图显示一个数据系列中各项目的占项目总和的百分比。
Matplotlib 提供了一个 pie() 函数,该函数可以生成数组中数据的饼状图。您可使用 x/sum(x) 来计算各个扇形区域占饼图总和的百分比。pie() 函数的参数说明如下:
pyplot.pie(x, explode=None, labels=None, colors=None, autopct=None)
- x: 数组序列,数组元素对应扇形区域的数量大小。
- labels: 列表字符串序列,为每个扇形区域备注一个标签名字。
- colors; 为每个扇形区域设置颜色,默认按照颜色周期自动设置。
- autopct: 格式化字符串"fmt%pct",使用百分比的格式设置每个扇形区的标签,并将其放置在扇形区内。
- pctdistance:设置百分比标签与圆心的距离;
- labeldistance:设置各扇形标签(图例)与圆心的距离;
- explode: 指定饼图某些部分的突出显示,即呈现爆炸式;()
- shadow:是否添加饼图的阴影效果
# 设置大小
plt.rcParams['figure.figsize'] = (5,5)
#定义饼的标签,
labels = ['娱乐','育儿','饮食','房贷','交通','其它']
#每个标签所占的数量
x = [200,500,1200,7000,200,900]
#绘制饼图
plt.pie(x,labels=labels)
百分比显示 percentage
autopct
#定义饼的标签,
labels = ['娱乐','育儿','饮食','房贷','交通','其它']
#每个标签所占的数量
x = [200,500,1200,7000,200,900]
plt.title("饼图示例-8月份家庭支出")
#%.2f%%显示百分比,保留2位小数
plt.pie(x,labels=labels,autopct='%.2f%%')
饼状图的分离
explode
: 指定饼图某些部分的突出显示
#定义饼的标签,
labels = ['娱乐','育儿','饮食','房贷','交通','其它']
#每个标签所占的数量
x = [200,500,1200,7000,200,900]
#饼图分离
explode = (0.03,0.05,0.06,0.04,0.08,0.21)
#设置阴影效果
plt.pie(x,labels=labels,autopct='%3.2f%%',explode=explode)
设置饼状图百分比和文本距离中心位置:
- pctdistance:设置百分比标签与圆心的距离;
- labeldistance:设置各扇形标签(图例)与圆心的距离;
#定义饼的标签,
labels = ['娱乐','育儿','饮食','房贷','交通','其它']
#每个标签所占的数量
x = [200,500,1200,7000,200,900]
#饼图分离
explode = (0.03,0.05,0.06,0.04,0.08,0.1)
#设置阴影效果
#plt.pie(x,labels=labels,autopct='%3.2f%%',explode=explode,shadow=True)
plt.pie(x,labels=labels,autopct='%3.2f%%',explode=explode, labeldistance=1.35, pctdistance=1.2)
图列
plt.legend()
#定义饼的标签,
labels = ['娱乐','育儿','饮食','房贷','交通','其它']
#每个标签所占的数量
x = [200,500,1200,7000,200,900]
#饼图分离
explode = (0.03,0.05,0.06,0.04,0.08,0.1)
#设置阴影效果
#plt.pie(x,labels=labels,autopct='%3.2f%%',explode=explode,shadow=True)
plt.pie(x,labels=labels,autopct='%3.2f%%',explode=explode, labeldistance=1.35, pctdistance=1.2)
plt.legend()