Seaborn系列(二):关系绘图

本文详细介绍了Seaborn库中relplot函数的散点图和折线图绘制技巧,涵盖颜色、样式、大小分组,以及如何利用hue、style、size参数进行多维度数据展示。从基础使用到高级定制,涵盖了tips和fmri数据集示例。

Seaborn系列目录



关系绘图、分布统计绘图、类别统计绘图是seaborn中最常用的功能。

1. 关系绘图API概述

统计分析就是了解数据变量之间的关系的过程。seaborn中“统计关系”绘图函数共三个:

  • relplot():通过kind参数指定为"scatter"或"line",可以绘制散点图和折线图。默认为scatter。
    • scatterplot():绘制散点图。绘图效果同replot(kind=“scatter”)
    • lineplot():绘制折线图。绘图效果同replot(kind=“line”)
  • relplot函数为figure级函数,返回FacetGrid对象。FacetGrid对象类似于figure。
  • scatterplot和lineplot函数为axes级函数,返回axes对象。

figure级函数与axes级函数区别见Seaborn系列(一):绘图基础、函数分类、长短数据类型支持

2. relplot散点图

  • sns.relplot(x=None,y=None,data=None,kind="scatter"):根据kind绘制折线图或散点图。
    • 常用参数简介
      • x,y参数:x,y坐标数据。x,y为数组或者是data的key名称(data为DataFrame时,x,y指列名称)。
      • data参数:data为类字典数据。当data不为空时,x,y可以用data的key引用数据。
      • kind参数:scatter指绘制散点图,line指绘制折线图。
    • 分组聚合参数
      • hue参数:用不同颜色对数组分组。hue可以是列表或者data的key。hue的每一个数据绘制一根曲线,给一个图例标签。
      • size参数:用不同点大小对数组分组。数组或者data中的key。每个大小给个图例标签。
      • style参数:用不同的点样式对数据分组。数组或者data中的key。每个样式给一个图例标签。
      • row,col:把row,col指定的数据按照行或列排列到不同的子图。
    • 分组聚合参数样式
      • palette参数:指定hue分组的每组曲线的颜色。
      • markers参数:设置True使用默认点样式。False不显示点。可以用列表为style设置对应点样式(长度必须和style分组数相同)。
      • sizes参数:把size映射到一个指定的区间。
    • 其他参数
      • legend参数:图例显示方式。False不现实图例。brief则hue和size的分组都取等间距样本作为图例。full则把分组内所有数值都显示为图例。auto则自动选择brief或full。
      • height参数:每个子图的高度(单位inch)
      • aspect参数:宽度=aspect×高度

hue,style,size类似,都是用于分组,hue根据颜色分组,style根据点先样式分组,size根据点大小或线粗细分组。每个组在曲线图中就是绘制一根单独的曲线。

以tips小费数据集为例。

>>> tips=sns.load_dataset('tips')
>>> tips
     total_bill   tip     sex smoker   day    time  size
0         16.99  1.01  Female     No   Sun  Dinner     2
1         10.34  1.66    Male     No   Sun  Dinner     3
2         21.01  3.50    Male     No   Sun  Dinner     3
3         23.68  3.31    Male     No   Sun  Dinner     2
4         24.59  3.61  Female     No   Sun  Dinner     4
..          ...   ...     ...    ...   ...     ...   ...
239       29.03  5.92    Male     No   Sat  Dinner     3
240       27.18  2.00  Female    Yes   Sat  Dinner     2
241       22.67  2.00    Male    Yes   Sat  Dinner     2
242       17.82  1.75    Male     No   Sat  Dinner     2
243       18.78  3.00  Female     No  Thur  Dinner     2

数据集为一个餐厅的小费数据。
total_bill为总账单、tip为小费金额;
sex为消费者性别,smoker为是否抽烟,size为用餐人数。
day、time分别为日期、时间。

2.1 relplot简单的关系绘图

sns.relplot(data=tips,x='total_bill',y='tip') #观察账单和小费的关系,绘制散点图
sns.relplot(data=tips,x='total_bill',y='tip',kind='line') #观察账单和小费的关系,绘制折线图

relplot1

relplot2

2.2 relplot颜色(hue)分组绘图

sns.relplot(data=tips,x='total_bill',y='tip',hue='day') #分别观察每天的账单和小费的关系。
sns.relplot(data=tips,x='total_bill',y='tip',hue='smoker') #分别观察抽烟和不抽烟人群的账单和小费的关系。
sns.relplot(data=tips,x='total_bill',y='tip',hue='size') #根据就餐人数,分别观察人群的账单和小费的关系。

relplot-散点图1_hue

relplot-散点图2_hue

relplot-散点图3_hue

hue分组后对不同的组用不同的颜色区分。

  • 用palette参数可以指定hue映射的颜色。palette参数可以是字符串、列表、字典或者colormap。
    • 字符串:color_palette()函数的参数。
      • seaborn的palette名称,比如deep,muted,bright,pastel,dark,colorblind等。
      • matplotlib的colormap名称,比如Oranges, coolwarm。
      • ‘hsl’或者’huls’:表示hsl颜色系统或者huls颜色系统。
      • 加关键字处理颜色:‘light:’, ‘dark:’, ‘blend:,’
      • cubehelix函数参数字符串‘ch:’:比如"ch:s=.25,rot=-.25",“ch:2,r=.2,l=.6”
    • 列表:比如(‘r’,‘b’,‘gray’)长度必须和hue分组数相同。
    • colormap:可以用字符串名称,比如"coolwarm"。也可以为colormap实例。
sns.relplot(data=tips,x='total_bill',y='tip',hue='day',palette='coolwarm')  #用colormap指定颜色
sns.relplot(data=tips,x='total_bill',y='tip',hue='day',palette='ch:start=2,rot=.5') #用cubehelix参数指定颜色
sns.relplot(data=tips,x='total_bill',y='tip',hue='day',palette=('r','g','b','gray')) #用列表参数指定颜色

relplot-散点图4_hue_palette

relplot-散点图5_hue_palette

relplot-散点图6_hue_palette

palette用列表或字典时,长度必须和hue分组数相同。比如上例中,day共有4种,因此,palette=(‘r’,‘b’,‘g’,‘gray’)是ok的。

2.3 relplot样式(style)分组绘图

style参数和hue类似,对参数不同的数据分组到不同的样式。

具体是什么样式有函数自行确定,或者根据marker参数确定。

#style分组
sns.relplot(data=tips,x='total_bill',y='tip',style="smoker")  #抽烟的人一个样式,不抽烟的人一个样式。
sns.relplot(data=tips,x='total_bill',y='tip',hue='smoker',style="smoker")  #组合样式
sns.relplot(data=tips,x='total_bill',y='tip',hue='smoker',style="time") #组合样式

#style+marker
sns.relplot(data=tips,x='total_bill',y='tip',style="time",markers=["o","*"]) #用markers参数指定style分组点样式

通常style的每个分组的点样式有系统自行决定。用marker可以自行指定,但是比较麻烦,且有限制,比如长度必须和style的分组个数相同;列表中只能全部是填充点,如(“o”,"*"),或者全部是线条点,比如("+",“x”)

relplot-散点图7_style

relplot-散点图8_style

relplot-散点图9_style

relplot-散点图10_style

size分组,区分点大小绘制

#size分组
sns.relplot(data=tips,x='total_bill',y='tip',size="smoker")#size分组(根据是否抽烟,分组)
sns.relplot(data=tips,x='total_bill',y='tip',hue='smoker',size="size")#hue+size
sns.relplot(data=tips,x='total_bill',y='tip',hue='day',style="size",size="smoker")#hue+style+size

#设置大小数值
sns.relplot(data=tips,x='total_bill',y='tip',hue='day',size="size",sizes=(10,200)) #把size映射到10-200区间,用于显示大小

对于散点图,style和size和hue相似都是分组参数,知识分组表示方法不同。hue用颜色区分,style用点样式区分,size用点大小区分。

relplot-散点图11_size

relplot-散点图12_size

relplot-散点图13_size

size参数可以直接用于设置点大小,但是size数据的大小不太适合显示,比如都特别小,或者差异不明显不便于观看,怎么办?
把size参数直接处理肯定是可以的,但是为了显示就破坏原始数据并不好。用sizes参数可以把size映射到一个指定的区间

relplot-散点图14_size

2.4 relplot多子图绘图

根据row和col参数值,可以把图形绘制到多个子图。每行表达row数据的一个值,每列表达col数据的一个值。

col_wrap

sns.relplot(data=tips,x='total_bill',y='tip',col='smoker')     #不同子图绘制smoker不同的图形,绘制在不同的行 
sns.relplot(data=tips,x='total_bill',y='tip',row='smoker',col='time') #用不同的行绘制子图区分smoker,不同的列子图区分time
sns.relplot(data=tips,x='total_bill',y='tip',hue='smoker',col='time') #根据time绘制多列子图,每个子图用hue分组
sns.relplot(data=tips,x='total_bill',y='tip',hue='smoker',col='day',col_wrap=2) #每列最多2个子图,超过2个自动换行

rowcol1
rowcol2
rowcol3
rowcol4

3. relplot折线图

折线图和散点图类似,kind参数设置为line,其他大部分参数都相同。

  • sns.relplot(x=None,y=None,data=None,kind="scatter"):根据kind绘制折线图或散点图。
    • 常用参数简介
      • x,y参数:x,y坐标数据。x,y为数组或者是data的key名称(data为DataFrame时,x,y指列名称)。
      • data参数:data为类字典数据。当data不为空时,x,y可以用data的key引用数据。
      • kind参数:scatter指绘制散点图,line指绘制折线图。
    • 分组聚合参数
      • hue参数:用不同颜色对数组分组。hue可以是列表或者data的key。hue的每一个数据绘制一根曲线,给一个图例标签。
      • size参数:用不同点大小对数组分组。数组或者data中的key。每个大小给个图例标签。
      • style参数:用不同的点样式对数据分组。数组或者data中的key。每个样式给一个图例标签。
      • row,col:把row,col指定的数据按照行或列排列到不同的子图。
    • 分组聚合参数样式
      • palette参数:指定hue分组的每组曲线的颜色。
      • markers参数:设置True使用默认点样式。False不显示点。可以用列表为style设置对应点样式(marker列表长度必须和style分组数相同)。
      • dashes参数:bool设置是否使用默认线样式(实线)。用列表为style分组设置对应线样式(列表长度必须和style分组数相同)。
      • sizes参数:把size映射到一个指定的区间。
    • 折线图专用参数
      • sort参数:是否对x排序。默认为True。False则按照数组中x的顺序绘图。
      • ci参数:,当存在x值对应多个y值时,用置信区间绘制线条,默认显示95%置信区间(confidence intervals)。
        • ci=None表示不显示置信区间。
        • ci='sd’表示显示标准偏差(standard deviation)而不是置信区间。
        • ci=数值:表示指定置信区间的数值。
      • estimator参数:聚合设置,默认为平均值
        • estimator=None:不使用聚合,x对应多个y就每个x坐标绘制多个y点。
        • estimator=func:聚合函数,比如mean,sum等。
    • 其他参数
      • legend参数:图例显示方式。False不现实图例。brief则hue和size的分组都取等间距样本作为图例。full则把分组内所有数值都显示为图例。auto则自动选择brief或full。
      • height参数:每个子图的高度(单位inch)
      • aspect参数:宽度=aspect×高度

3.1 relplot折线图(是否自动排序绘图)

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
df=pd.DataFrame(np.random.randn(500, 2).cumsum(axis=0), columns=["x", "y"])

sns.relplot(data=df,x="x",y="y",kind="line")
sns.relplot(data=df,x="x",y="y",kind="line",sort=False)
plt.show()

line1

line2

折线图默认会把坐标按x从小到大排序。参数sort设置为False,则不排序。

3.2 示例数据集

以fmri数据集为例

>>> fmri=sns.load_dataset('fmri')
>>> fmri
fmri
     subject  timepoint event    region    signal
0        s13         18  stim  parietal -0.017552
1         s5         14  stim  parietal -0.080883
2        s12         18  stim  parietal -0.081033
3        s11         18  stim  parietal -0.046134
4        s10         18  stim  parietal -0.037970
...      ...        ...   ...       ...       ...
1059      s0          8   cue   frontal  0.018165
1060     s13          7   cue   frontal -0.029130
1061     s12          7   cue   frontal -0.004939
1062     s11          7   cue   frontal -0.025367
1063      s0          0   cue  parietal -0.006899

fmri是一组事件相关功能核磁共振成像数据。
subject为14个测试者。timpoint为时间点。event为事件,分为刺激stim和暗示cue。region为区域,分为额叶和前叶。signal为信号。

3.3 relplot折线图(x,y一对多,聚类绘制)

import matplotlib.pyplot as plt
import seaborn as sns
fmri=sns.load_dataset('fmri')

sns.relplot(data=fmri,x="timepoint",y="signal",kind="line")
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",ci=None)

plt.show()

line3

line4

line5_ci

line6_ci_50

注意时间和信号并非一一对应,而是一个x对应多个y值。所以线条显示的是y的平均值,填充色把y的95%置信区间范围显示出来了。

对于大数据集,绘制置信区间可能需要较多时间。设置ci=None可以禁用绘制置信区间。
设置ci='sd’绘制标准差,而不是置信区间,对较大数据也是要给不错的选择。

折线图(x,y一对多,关闭聚合,不绘制均值也也不绘制置信区间)

estimator=None可以关闭聚合设置,直接用x,y点绘图,即每个x绘制多个y,当然这样绘制的图形可能会比较奇怪。

estimator也可以设置为聚合函数(如sum,mean,max等),用聚合函数将一个x值对应的多个y值计算成一个值。

import matplotlib.pyplot as plt
import seaborn as sns
fmri=sns.load_dataset('fmri')

# sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",estimator=None) #不聚合
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",estimator=sum) #聚合函数为sum

plt.show()

line8_estimator

注意y坐标值为sum。

3.4 relplot分组绘图(hue、style、size)

import matplotlib.pyplot as plt
import seaborn as sns
fmri=sns.load_dataset('fmri')

sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",hue="event") #hue分组
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",style="event") #style分组
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",size="event") #size分组

plt.show()

line9_分组hue

line10_分组style

line11_分组size

sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",hue="event",style="region") #hue+style
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",hue="event",size="region") #hue+size
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",style="event",size="region") #hue+size

line12_分组hue+style

line13_分组hue+size

line14_分组style+size

sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",hue="event",style="event",size="region") #hue+style+size

line15_分组hue+style+size

3.5 relplot分组绘图样式

hue分组可以用palette设置颜色样式
style分组可以用markers设置点样式,用dashes设置线样式
size分组可以用sizes设置线粗细

import matplotlib.pyplot as plt
import seaborn as sns
fmri=sns.load_dataset('fmri')

sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",hue="region",palette="hsv") #颜色样式
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",style="region",markers=["o","*"]) #style点样式
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",style="region",dashes=[[5,1],[1,0]]) #style线样式
sns.relplot(data=fmri,x="timepoint",y="signal",kind="line",size="region",sizes=[0.5,2]) #size大小

plt.show()

注意:

  1. dashes参数用列表时,列表长度必须和style分组个数相同。
  2. dashes线样式用[线长度,空白长度,线长度,空白长度,...]列表形式自定义线条样式

line16_分组样式palette

line17_分组样式markers

line18_分组样式dashes

line19_分组样式sizes

4. scatterplot散点图

scatterplot和使用relplot绘制散点图类似,主要区别:

  • 少了kind参数,以及row,col参数。
  • 多了个ax参数。
import matplotlib.pyplot as plt
import seaborn as sns
tips=sns.load_dataset('tips')

sns.scatterplot(data=tips,x="total_bill",y="tip")

plt.show()

因为scatterplot是axes级函数

  • 返回值是一个axes
  • 可以用ax指定axes。
    • 不指定ax时,会在默认的axes中绘图。
    • 不指定ax,多次调用scatterplot绘图都会在默认(同一个)的axes中绘图。
import matplotlib.pyplot as plt
import seaborn as sns
tips=sns.load_dataset('tips')
fig=plt.figure()
ax1=fig.add_subplot(121)
ax2=fig.add_subplot(122)
#ax1,ax2=fig.subplots(1,2)

sns.scatterplot(data=tips,x="total_bill",y="tip",hue='smoker',ax=ax1)
sns.scatterplot(data=tips,x="total_bill",y="tip",hue='smoker',size='sex',ax=ax2)

plt.show()

scatterplot_ax

5. lineplot折线图

lineplot和使用relplot绘制折线图类似,主要区别:

  • 少了kind参数,以及row,col参数。
  • 多了个ax参数。
import matplotlib.pyplot as plt
import seaborn as sns
fmri=sns.load_dataset('fmri')

sns.lineplot(data=fmri,x="timepoint",y="signal")

plt.show()

因为lineplot是axes级函数

  • 返回值是一个axes
  • 可以用ax指定axes。
    • 不指定ax时,会在默认的axes中绘图。
    • 不指定ax,多次调用lineplot绘图都会在默认(同一个)的axes中绘图。
import matplotlib.pyplot as plt
import seaborn as sns
fmri=sns.load_dataset('fmri')
fig=plt.figure()
(ax1,ax2),(ax3,ax4)=fig.subplots(2,2)

sns.lineplot(data=fmri,x="timepoint",y="signal",ax=ax1)
sns.lineplot(data=fmri,x="timepoint",y="signal",hue='region',ax=ax2)
sns.lineplot(data=fmri,x="timepoint",y="signal",hue='region',style='event',ax=ax3)
sns.lineplot(data=fmri,x="timepoint",y="signal",hue='region',size='event',ax=ax4)

plt.show()

lineplot1_ax



Seaborn系列目录


个人总结,部分内容进行了简单的处理和归纳,如有谬误,希望大家指出,持续修订更新中。

修订历史版本见:https://github.com/hustlei/AI_Learning_MindMap

未经允许请勿转载。

### 方法和技术概述 对于自动驾驶汽车或机器人中的LiDAR点云流,移动事件检测算法旨在识别场景中物体的运动状态变化。这些方法通常依赖于时间序列数据处理和多帧对比分析来区分静态背景与动态目标。 #### 基于特征匹配的方法 一种常见的策略是从连续扫描之间提取几何特性并进行比较。通过计算相邻时刻之间的差异向量场可以捕捉到局部位移模式[^1]。具体实现上,可以从每一帧构建描述子(descriptor),比如法线方向直方图、曲率分布等,并利用最近邻搜索找到对应关系;当发现显著偏离预期位置的情况时,则认为发生了相对运动。 ```python import numpy as np def compute_normal_histogram(point_cloud): """ 计算给定点云上的表面法线直方图 """ normals = estimate_normals(point_cloud) # 需要定义此函数以估算每一点处的法线 hist_bins = np.linspace(-np.pi, np.pi, num=36) histograms = [] for normal in normals: angle = np.arctan2(normal[1], normal[0]) histogram, _ = np.histogram(angle, bins=hist_bins) histograms.append(histogram) return np.array(histograms) def detect_motion_between_frames(frame_a, frame_b): """ 使用特征匹配技术判断两帧间是否存在明显变动 """ desc_a = compute_normal_histogram(frame_a) desc_b = compute_normal_histogram(frame_b) distances = cdist(desc_a, desc_b, metric='euclidean') matches = find_matches(distances) # 定义find_matches() 来查找最佳配对 motion_detected = any([d > threshold for d in distances.flatten()]) return motion_detected ``` #### 动态聚类分析 另一种有效的方式是对累积一段时间内的观测结果实施无监督学习过程——即先将所有可能属于同一对象的数据分组在一起形成簇(cluster),再评估各簇中心随时间的变化趋势。如果某个特定集合的位置参数表现出持续性的偏移迹象,那么就可推断该区域存在活动实体。 这种方法的优势在于能够适应复杂环境下的遮挡情况以及不规则形状的目标跟踪需求。同时还可以引入额外约束条件如速度上限、加速度范围等进一步提高准确性。 #### 时间窗口内统计检验 考虑到实际应用环境中噪声干扰因素较多,在设计具体的判定准则之前往往还需要考虑鲁棒性和实时性要求。因此建议采用滑动窗口机制收集历史记录作为参照系,并基于贝叶斯决策理论框架下执行假设测试: - H₀ : 当前观察值符合静止模型预测; - H₁ : 存在新的动力学行为影响了测量输出。 通过对似然比取自然对数得到log-LR指标后设定阈值即可完成最终分类操作。 ```python from scipy.stats import norm class MovingEventDetector(object): def __init__(self, window_size=5): self.window_size = window_size self.history = [] def update(self, new_observation): if len(self.history) >= self.window_size: del self.history[0] self.history.append(new_observation) def is_moving_event_occurred(self): mean_static_model = calculate_mean_of_static_model() log_likelihood_ratio_sum = sum([ np.log(norm.pdf(x, loc=mean_static_model)) - np.log(calculate_dynamic_distribution(x)) for x in self.history]) return abs(log_likelihood_ratio_sum) > decision_threshold detector = MovingEventDetector(window_size=7) for t in range(TIME_STEPS): observation_t = get_next_lidar_scan(t) detector.update(observation_t) if detector.is_moving_event_occurred(): print(f"Detected moving event at time step {t}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hustlei

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值