二、关联图之气泡图
1. 变散点为气泡
import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline midwest = pd.read_csv("https://raw.githubusercontent.com/selva86/datasets/master/midwest_filter.csv")
1 #plt.style.use('seaborn-whitegrid') 2 #sns.set_style("white") 3 4 #预设图像的各种属性 5 large = 22; med = 16; small = 12 6 params = {'axes.titlesize': large, #子图上的标题字体大小 7 'legend.fontsize': med, #图例的字体大小 8 'figure.figsize': (16, 10), #图像的画布大小 9 'axes.labelsize': med, #标签的字体大小 10 'xtick.labelsize': med, #x轴上的标尺的字体大小 11 'ytick.labelsize': med, #y轴上的标尺的字体大小 12 'figure.titlesize': large} #整个画布的标题字体大小 13 plt.rcParams.update(params) #设定各种各样的默认属性 14 #plt.style.use('seaborn-whitegrid') #设定整体风格 15 #sns.set_style("white") #设定整体背景风格 16 17 %matplotlib inline 18 19 #准备标签列表 20 categories = np.unique(midwest['category']) 21 colors = [plt.cm.tab10(i/float(len(categories)-1)) for i in range(len(categories))] 22 23 #布置画布 24 fig = plt.figure(figsize=(14,8), dpi=120, facecolor='w', edgecolor='k') 25 26 #循环绘图 27 #之前在给散点加入颜色的时候,我们提到X轴,Y轴上的值和我们的颜色是一一对应的 28 #那只要点的尺寸和我们的坐标点(x1,x2)一一对应,那我们就可以相应地给每一个点添加尺寸信息 29 for i, category in enumerate(categories): 30 plt.scatter('area', 'poptotal', data=midwest.loc[midwest.category==category, :] 31 #, s = midwest.loc[midwest.category==category, "percasian"]*500 #调整尺寸,让散点图成为气泡图 32 , s = "popasian" #现在的特征为我们的点的尺寸大小 33 #, s=20 #size 34 , c= np.array(colors[i]).reshape(1,-1) 35 , label=str(category) 36 , edgecolors = np.array(colors[i]).reshape(1,-1) #点的边缘的颜色 37 #, edgecolors="k" 38 , alpha = 0.7 #图像的透明度 39 , linewidths=0.5 #点的外圈的线条的宽度 40 ) 41 42 #装饰图像 43 plt.gca().set(xlim=(0.0, 0.12), ylim=(0, 90000), 44 xlabel='Area', ylabel='Population') 45 plt.xticks(fontsize=12) 46 plt.yticks(fontsize=12) 47 plt.title("Bubble Plot with Encircling", fontsize=22) 48 plt.legend(fontsize=12 49 ,markerscale=0.5 #现有的图例气泡的某个比例 50 ) 51 plt.show()
带标签的气泡
1 #plt.style.use('seaborn-whitegrid') 2 #sns.set_style("white") 3 4 #预设图像的各种属性 5 large = 22; med = 16; small = 12 6 params = {'axes.titlesize': large, #子图上的标题字体大小 7 'legend.fontsize': med, #图例的字体大小 8 'figure.figsize': (16, 10), #图像的画布大小 9 'axes.labelsize': med, #标签的字体大小 10 'xtick.labelsize': med, #x轴上的标尺的字体大小 11 'ytick.labelsize': med, #y轴上的标尺的字体大小 12 'figure.titlesize': large} #整个画布的标题字体大小 13 plt.rcParams.update(params) #设定各种各样的默认属性 14 #plt.style.use('seaborn-whitegrid') #设定整体风格 15 #sns.set_style("white") #设定整体背景风格 16 17 %matplotlib inline 18 19 #准备标签列表 20 categories = np.unique(midwest['category']) 21 colors = ["red","orange","pink"] 22 23 #布置画布 24 fig = plt.figure(figsize=(14,8), dpi=120, facecolor='w', edgecolor='k') 25 26 #循环绘图 27 for i, category in enumerate(["AHR","HAU","LHU"]): 28 data_ = midwest.loc[midwest.category==category, :] 29 data_.index = range(data_.shape[0]) 30 plt.scatter('area', 'poptotal', data=data_ 31 , s= midwest.loc[midwest.category==category, "poppovertyknown"]*0.05 #调整尺寸,让散点图成为气泡图 32 , c= colors[i] 33 , label=str(category) 34 , edgecolors= colors[i] 35 , alpha = 0.7 36 , linewidths=.5 37 ) 38 for i in range(midwest.loc[midwest.category==category, :].shape[0]): 39 plt.text(data_.loc[i,"area"] 40 ,data_.loc[i,"poptotal"] 41 ,s=data_.loc[i,"county"] #虽然参数都写作s,但这里的s指的是字符串string的s,不是size的s 42 ,fontdict={"fontsize":8} #调整我们的字符串的字体大小 43 ,horizontalalignment='right' #相对于我的气泡,把我的字符串显示在哪里 44 ) 45 46 #装饰图像 47 plt.gca().set(xlim=(0.0, 0.1), ylim=(0, 90000), 48 xlabel='Area', ylabel='Population') 49 plt.xticks(fontsize=12) 50 plt.yticks(fontsize=12) 51 plt.title("Bubble Plot with Encircling", fontsize=22) 52 lgnd = plt.legend(fontsize=12 53 ,markerscale=0.2 54 ) 55 plt.show()
2. 将散点框起来
什么时候会存在这样的需求呢?来看一组数据:
1 import matplotlib.pyplot as plt 2 import numpy as np; np.random.seed(1) #随机模式1号 3 4 #random.randn 取出符合标准正态分布的随机数 5 #random.normal 取出符合正态分布的随机数 6 x1, y1 = np.random.normal(loc=5 #正态分布中的均值 7 , scale=2 #正态分布中的方差 8 , size=(2,15) #生成怎样的数据结构,2列,每列15个数据 9 )
我们希望能够绘制一个边界,将同一类的点框起来。
在这里我们将用到SciPy库,这是一个专为Python设计的,专注于数学&工程学的库
今天我们将用到SciPy中专门处理空间算法和数据结构的模块:SciPy库中的spatial
scipy.spatial.ConvexHull()
ConvexHull直译是凸包,表示在一个平面上,我们能找到的最小的将一组数据全部包括在内的凸集
通俗的来说凸包就是包围一组散点的最小凸边形
相对的我们也有凹边形
类ConvexHull能够帮助我们创建N维凸包
重要参数
points:浮点数组成的n维数组,结构为(点的个数,维度)。表示用来构成凸包的坐标点。
incremental:布尔值,可不填。允许不断向类中添加新的数据点。
重要属性
vertices:组成凸包的那些数据点在原数据中的索引
*更多参数和属性走:https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.spatial.ConvexHull.html
1 from scipy.spatial import ConvexHull 2 from matplotlib import patches 3 #patches,给现有图像打补丁的包,在现有的图像上增加更多的东西 4 5 #定义绘制凸包的函数 6 def encircle(x,y, ax=None, **kw): 7 if not ax: ax=plt.gca() #获取当前子图,如果当前子图不存在,那就创建新的子图(get current ax) 8 p = np.c_[x,y] #.c_功能类似于zip,不过不是生成组合的元祖,而是生成拼接起来的数组array 9 hull = ConvexHull(p) #将数据集输入到ConvexHull中,自动生成凸包类型的对象 10 poly = plt.Polygon(p[hull.vertices,:], **kw) 11 #使用属性vertices调用形成凸包的点的索引,进行切片后,利用绘制多边形的类plt.Polygon将形成凸包的点连起来 12 #这里的**kw就是定义函数的时候输入的**kw,里面包含了一系列可以在绘制多边形的类中进行调节的内容 13 #包括多边形的边框颜色,填充颜色,透明度等等 14 ax.add_patch(poly) #使用add_patch,将生成的多边形作为一个补丁补充到图像上 15 16 17 plt.scatter(x1, y1) 18 plt.scatter(x2, y2) 19 20 encircle(x1, y1 21 , ec="k" #线条的颜色 22 , fc="gold" #多边形的颜色 23 , alpha=0.2 #图像整体的透明度 24 ) 25 #你是否注意到,边框也是透明的? 26 27 encircle(x2, y2, ec="orange", fc="none") 28 29 plt.show()
完整绘图
1 from scipy.spatial import ConvexHull 2 from matplotlib import patches 3 4 plt.style.use('seaborn-whitegrid') 5 sns.set_style("white") 6 7 #预设图像的各种属性 8 large = 22; med = 16; small = 12 9 params = {'axes.titlesize': large, #子图上的标题字体大小 10 'legend.fontsize': med, #图例的字体大小 11 'figure.figsize': (16, 10), #图像的画布大小 12 'axes.labelsize': med, #标签的字体大小 13 'xtick.labelsize': med, #x轴上的标尺的字体大小 14 'ytick.labelsize': med, #y轴上的标尺的字体大小 15 'figure.titlesize': large} #整个画布的标题字体大小 16 plt.rcParams.update(params) #设定各种各样的默认属性 17 plt.style.use('seaborn-whitegrid') #设定整体风格 18 sns.set_style("white") #设定整体背景风格 19 20 %matplotlib inline 21 22 #准备标签列表 23 categories = np.unique(midwest['category']) 24 colors = [plt.cm.tab10(i/float(len(categories)-1)) for i in range(len(categories))] 25 26 #布置画布 27 fig = plt.figure(figsize=(16, 10), dpi=120, facecolor='w', edgecolor='k') 28 29 #循环绘图 30 for i, category in enumerate(categories): 31 plt.scatter('area', 'poptotal', data=midwest.loc[midwest.category==category, :] 32 , s="popasian" #调整尺寸,让散点图成为气泡图 33 , c= np.array(colors[i]).reshape(1,-1) 34 , label=str(category) 35 , edgecolors= np.array(colors[i]).reshape(1,-1) 36 , alpha = 0.7 37 , linewidths=.5) 38 39 #绘制凸包 40 41 #定义函数 42 def encircle(x,y, ax=None, **kw): 43 if not ax: ax=plt.gca() 44 p = np.c_[x,y] 45 hull = ConvexHull(p) 46 poly = plt.Polygon(p[hull.vertices,:], **kw) 47 ax.add_patch(poly) 48 49 #定义需要被框起来的数据:所有在IN州中的城市 50 midwest_encircle_data = midwest.loc[midwest.state=='IN', :] 51 52 #使用函数绘制 53 54 #这里绘制的是金色的面 55 encircle(midwest_encircle_data.area 56 , midwest_encircle_data.poptotal 57 , ec="k" 58 , fc="gold" 59 , alpha=0.1 60 ) 61 62 #这里绘制的是浅蓝色的线,而面是透明的 63 encircle(midwest_encircle_data.area 64 , midwest_encircle_data.poptotal 65 , ec="lightblue" #线条颜色 66 , fc="none" #填充颜色 67 , linewidth=1.5 #线宽 68 ) 69 70 #装饰图像 71 plt.gca().set(xlim=(0.0, 0.12), ylim=(0, 90000), 72 xlabel='Area', ylabel='Population') 73 74 plt.xticks(fontsize=12); plt.yticks(fontsize=12) 75 plt.title("Bubble Plot with Encircling", fontsize=22) 76 plt.legend(markerscale=0.6) 77 plt.show()