•凸包:在一个平面内,我们能够找到的最小的将一组数据全部包括在内的凸集,通俗来说凸包就是包围一组散点的最小凸边形!!
•凸边形即为对外的角都不为钝角!!图二,图三都有向外的钝角即不为凸边形
•在计算机视觉技术中,我们经常需要使用凸包,以帮助
计算机识别图像的轮廓!!!
•首先,需要绘制基础的散点图:
import numpy as np;np.random.seed(1) # 确定以固定的模式生成随机数 (1)中的数字可随便写
import matplotlib.pyplot as plt
x1, y1 = np.random.normal(loc=5 # 正态分布的均值
, scale=2 # 正态分布的方差
, size=(2, 15)) # 生成2列15行的数据 分别对应x1 y1
x2, y2 = np.random.normal(loc=8
, scale=2.5
, size=(2, 13))
plt.scatter(x1, y1)
plt.scatter(x2, y2)
plt.show()
•random.randn
取出符合标准正态分布的随机数,期望值(均值)=0 方差=1
•random.normal
取出符合自定义正态分布的随机数 均值与方差均可自定义
•上述图片是我们绘制的基本散点图,下一步使用spatial给散点图添加凸包
•首先自定义绘制凸包的函数,包括各种属性,在使用该函数绘制凸包即可完成!!
import numpy as np;np.random.seed(1)# 确定以固定的模式生成随机数 (1)中的数字可随便写
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
x1, y1 = np.random.normal(loc=5 # 正态分布的均值
, scale=2 # 正态分布的方差
, size=(2, 15)) # 生成2列15行的数据 分别对应x1 y1
x2, y2 = np.random.normal(loc=8
, scale=2.5
, size=(2, 13))
plt.scatter(x1, y1)
plt.scatter(x2, y2)
# 定义绘制凸包的函数
def encircle(x, y, ax=None, **kw):
if not ax: ax = plt.gca()
p = np.c_[x, y] # c_功能类似于zip,是生成拼接起来的数组array
hull = ConvexHull(p) # 将数据集输入到ConvexHull()中,自动生凸包对象
poly = plt.Polygon(p[hull.vertices, :], **kw)
ax.add_patch(poly)
# 调用凸包函数
encircle(x1, y1,
ec='k', # 线条的颜色
fc='gold', # 多边形的颜色
alpha=0.2) # 图像整体的透明度
encircle(x2, y2, ec='orange', fc='none')
plt.show()
代码解读:
•(1)导入我们所需的库numpy ,matplotlib ,scipy
并确定以固定的模式生成随机数
•(2)绘制基础散点图
•(3)定义绘制凸包的函数,以及其中的属性
•(4)调用凸包函数,并确定其中的属性
•(5)显示图片
•凸包的本质为:在已经绘制完成的散点图上添加凸包线条
•凸包函数中的 x y
分别为横坐标,纵坐标,ax
参数是获取绘制好的散点图,
•if not ax: ax = plt.gca()
判断前面是否绘制过子图(当前散点图),gca()
的作用:有就获取当前子图,否则就创建新的子图
•p = np.c_[x, y]
c_功能类似于zip,是生成拼接起来的数据集,类型为array(数组)
•hull = ConvexHull( p )
将数据集p输入到ConvexHull()中,自动生凸包对象 注意:数据集p必须为数组
•poly = plt.Polygon(p[hull.vertices, :], **kw)
,使用p[hull.vertices, :]
获取凸点的横,纵坐标,再使用Polygon
函数将所有的凸点连接起来形成多边形 kw
就是定义函数的kw,里面包含一系列绘制多边形需要调节的属性,包括边框颜色,填充颜色,透明度等等
•ax.add_patch(poly)
将生成的多边形添加到子图中(散点图)
•最后调用凸包函数,确定必要的属性即可完成绘制凸包
•在上篇博客中我们已经成功绘制了气泡图:Python数据可视化之气泡图(图文并茂详细版!!!)
•我们将选取美国中西部数据集的一个州,来绘制上图中的凸包
•选取IN这个州来绘制凸包
代码测试:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from scipy.spatial import ConvexHull
# 导入数据
midwest = pd.read_csv(r'D:\9\midwest_filter.csv')
# 预设图像各种信息
large = 22
med = 16
small = 12
params = {'axes.titlesize': large, # 子图上的标题字体大小
'legend.fontsize': med, # 图例的字体大小
'figure.figsize': (med, small), # 画布大小
'axes.labelsize': med, # 标签的字体大小
'xtick.labelsize': med, # x轴标尺的字体大小
'ytick.labelsize': med, # y轴标尺的字体大小
'figure.titlesize': large} # 整个画布的标题字体大小
plt.rcParams.update(params) # 设定各种默认属性
plt.style.use('seaborn-whitegrid') # 设置整体风格
sns.set_style('white') # 设置整体背景风格
# 准备标签列表与颜色列表
categories = np.unique(midwest['category'])
colors = [plt.cm.tab10(i / float(len(categories) - 1)) for i in range(len(categories))]
# 布置画布
fig = plt.figure(figsize=(14, 8), dpi=120, facecolor='w', edgecolor='k')
for i, category in enumerate(categories):
plt.scatter('area', 'poptotal', data=midwest.loc[midwest.category == category, :]
, s=midwest.loc[midwest.category == category, 'percasian'] * 500 # 需要对比的属性
# ,s='percasian'
, c=np.array(colors[i]).reshape(1, -1) # 点的颜色
, edgecolors=np.array(colors[i]).reshape(1, -1) # 点的边缘颜色
, label=str(category) # 标签
, alpha=0.7 # 透明度
, linewidths=.5) # 点的边缘线的宽度
# 绘制凸包
# 定义函数
def encircle(x, y, ax=None, **kw):
if not ax: ax = plt.gca()
p = np.c_[x, y]
hull = ConvexHull(p)
poly = plt.Polygon(p[hull.vertices, :], **kw)
ax.add_patch(poly)
# 定义需要被框起来的数据:所有在in州中的城市
midwest_encircle_data = midwest.loc[midwest.state == 'IN'
, :]
# 使用函数绘制
encircle(midwest_encircle_data.area,
midwest_encircle_data.poptotal,
ec='k',
fc='gold',
alpha=0.1)
# 绘制包围的淡蓝色的线
encircle(midwest_encircle_data.area,
midwest_encircle_data.poptotal,
ec='lightblue',
fc='none',
linewidth=1.5)
# 装饰图像
plt.gca().set(xlim=(0.0, 0.12), ylim=(0, 90000),
xlabel='Area', ylabel='Population')
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.title('Bubble Plot Encircling', fontsize=22)
lgnd = plt.legend(fontsize=12)
plt.show()