如何用Seaborn基于含向量元素的Pandas DataFrame绘制多线图?
如何优雅地用Seaborn绘制含列表型列的DataFrame折线图(支持hue/style分组)
我非常喜欢用Seaborn绘制pandas DataFrame时的hue=和style=这类分组/分类关键字参数,比如处理标量值的散点图时非常方便:
import pandas as pd import seaborn as sns import numpy as np df = pd.DataFrame({'x':[[1,2,3],[1,2,3,4],[1,2,3]], 'y':[[1,2,3],[4,4,8,3],[3,6,8]], 'cat1': ['x','y','x'], 'cat2': ['a','b','c']}) df[['x_mean','y_mean']] = df[['x','y']].applymap(np.mean) # 标量值散点图,轻松实现分组 sns.scatterplot(data=df, x='x_mean', y='y_mean', style='cat1', hue='cat2')

但这种方式只适用于均值这类标量值。当我想把'y'随'x'变化绘制成多条折线时,只能用两种不太方便的方法:
- 遍历每一行:
# 折线图无法直接用分组参数 for i, row in df.iterrows(): sns.lineplot(data=row, x='x', y='y', style='cat1', hue='cat2')

此时style和hue完全无法正常工作,还要手动定义映射、创建图例,非常麻烦。
- 展开
'x'和'y'列,但对大型数组来说效率太低。
有没有更优雅的实现方法?
解决方案:将列表型列展开为长格式DataFrame
核心思路是把每行的x和y列表拆成一一对应的行,同时保留分组列cat1、cat2的信息,这样就能直接用Seaborn的hue和style参数了。
步骤1:为每行添加唯一标识(可选但推荐)
给每行加一个id列,方便后续区分不同的折线:
df['id'] = df.index
步骤2:同时展开x和y列
利用pandas的explode方法,同时对x和y列进行展开,确保每个x值对应正确的y值:
df_long = df.explode(['x', 'y'], ignore_index=True) # 转换数值类型(explode后可能为字符串,视情况处理) df_long[['x', 'y']] = df_long[['x', 'y']].astype(int)
步骤3:用Seaborn绘制折线图
现在可以直接使用hue和style参数,还能通过units指定每条折线的独立标识:
sns.lineplot(data=df_long, x='x', y='y', hue='cat2', style='cat1', units='id', estimator=None)
这样绘制的折线图会自动根据cat1设置线条样式,cat2设置颜色,并且生成正确的分组图例,完全不需要手动处理映射。
完整代码
import pandas as pd import seaborn as sns import numpy as np df = pd.DataFrame({'x':[[1,2,3],[1,2,3,4],[1,2,3]], 'y':[[1,2,3],[4,4,8,3],[3,6,8]], 'cat1': ['x','y','x'], 'cat2': ['a','b','c']}) # 添加唯一标识 df['id'] = df.index # 展开列表列 df_long = df.explode(['x', 'y'], ignore_index=True) df_long[['x', 'y']] = df_long[['x', 'y']].astype(int) # 绘制分组折线图 sns.lineplot(data=df_long, x='x', y='y', hue='cat2', style='cat1', units='id', estimator=None)
这种方法相比手动遍历更简洁,相比手动展开更高效,完美利用了Seaborn的分组功能。
内容的提问来源于stack exchange,提问作者Niclas
相关产品推荐
相关产品推荐

