参考ggplot2,Seaborn将迎来超大版本更新!

语言: CN / TW / HK

最新消息, Seaborn将迎来API重写级别 版本更新,本文罗列重大改变,太值得期待了!

  • Matplotlib是Python最重要的可视化库,但是,过于复杂,Seaborn对其主要功能做了封装,隐藏复杂参数,仅需要几行代码就可以实现优美的统计图,但功能有限: Seaborn

  • 此次更新主要拓展Seaborn的核心功能 — 与pandas的集成、数据和图形之间的自动映射、统计转换 — 使得Seaborn成为一个更具组合性、可扩展性和全面性的可视化库。
  • 作者直言,更新灵感不少源于R语言中 ggplot2背后的图层图形语法 ,去其糟粕,取其精华,做了很多优化,但是Seaborn不等于Python版ggplot2 ( plotnine );

  • 为了这次更新,已经开发了8个月,依旧还有很多工作要做, 更新版具体发布时间待定 ,但是会在发布前发布系列alpha/beta releases,以获取测试反馈。

:point_down::point_down: 下面看看主要哪些方面发生了更新 :point_down::point_down:

嫌长文,直接看文章末尾小结。

基本语法

导入Seaborn

#方法一
import seaborn.objects as so #不再是import seaborn as sns

#方法二
from seaborn.objects import *

绘图主函数 变成了 seaborn.objects.Plot

import seaborn
tips = seaborn.load_dataset("tips") #导入内置数据

so.Plot(tips, x="total_bill", y="tip") #绘制空Figure

add在Figure上添加散点图层,

so.Plot(tips, x="total_bill", y="tip").add(so.Scatter()) 
#.add(so.Scatter())是不是有ggplot2 + 添加图层的影子~

全局个性化,

so.Plot(tips).add(so.Scatter(), x="total_bill", y="tip")

每个图层个性化,

(
so.Plot(tips, x="total_bill", y="tip")
.add(so.Scatter(color=".6"))
.add(so.Scatter(), data=tips.query("size == 2"))
)
(
so.Plot(tips, x="total_bill", y="tip", color="day", fill="time")
.add(so.Scatter(fillalpha=.8))
)

核心组件1-图层对象Mark

每个图层都需要一个Mark对象,它定义了如何绘制绘图。将对应于现有seaborn功能和提供新功能的标记,但是,很多还没有实现,

so.Plot(tips, y="day", x="total_bill")
.add(so.Dot(color="#698", alpha=.5)) #直接设置Mark(此处为Dot)特性,而不是映射它们.

核心组件2-数据转换Stat

在新版本中,每个层都可以接受一个数据转换的Stat对象,

so.Plot(fmri, x="timepoint", y="signal", color="event").add(so.Line(), so.Agg(), group="subject")

自定义Mark和Stat对象

class PeakAnnotation(so.Mark):
def _plot_split(self, keys, data, ax, kws):
ix = data["y"].idxmax()
ax.annotate(
"The peak", data.loc[ix, ["x", "y"]],
xytext=(10, -100), textcoords="offset points",
va="top", ha="center",
arrowprops=dict(arrowstyle="->", color=".2"),

)

(
so.Plot(fmri, x="timepoint", y="signal")
.add(so.Line(), so.Agg())
.add(PeakAnnotation(), so.Agg())
)

核心组件3-图形自适应the Move

新版本里,图形的一些调整都汇聚在move对象中,取代老版本中的 dodge=xxjitter=xx、multiple= xx等设置,

(
so.Plot(tips, "day", "total_bill", color="time", alpha="sex")
.add(so.Bar(), so.Agg(), move=so.Dodge())
)
(
so.Plot(tips, "day", "total_bill", color="time", alpha="smoker")
.add(so.Dot(), move=[so.Dodge(by=["color"]), so.Jitter(.5)])
)

个性化设置

新版本将添加更多图形个性化设置功能,

(
so.Plot(planets, x="mass", y="distance", color="year")
.map_color("flare", norm=(2000, 2010))
.scale_numeric("x", "log")
.add(so.Scatter(pointsize=3))
)
#以上设置顺序不分先后
(
so.Plot(planets, y="year", x="orbital_period")
.scale_numeric("x", "log")
.add(so.Scatter(alpha=.5, marker="x"), color="method")
.add(so.Line(linewidth=2, color=".2"), so.Agg(), orient="h")
)

子图定义

新版本中分面Facet被隐式地内置,

(
so.Plot(tips, x="total_bill", y="tip")
.facet("time", order=["Dinner", "Lunch"])
.add(so.Scatter())
)

注意区别于老版本的FacetGrid,

(
so.Plot(tips, x="total_bill", y="tip", col="day")
.add(so.Scatter(color=".75"), col=None)
.add(so.Scatter(), color="day")
.configure(figsize=(7, 3))
)

新版本依旧包含 PairGrid功能,

(
so.Plot(tips, y="day")
.pair(x=["total_bill", "tip"])
.add(so.Dot())
)

FacetGrid和 PairGrid可联合使用,

(
so.Plot(tips, x="day")
.facet("sex")
.pair(y=["total_bill", "tip"])
.add(so.Dot())
)

faceted和paired图均可沿着列和行“ wrapped ”,

class Histogram(so.Mark):  # TODO replace once we implement
def _plot_split(self, keys, data, ax, kws):
ax.hist(data["x"], bins="auto", **kws)
ax.set_ylabel("count")

(
so.Plot(tips)
.pair(x=tips.columns, wrap=3)
.configure(sharey=False)
.add(Histogram())
)

总之,新版本中,“axes-level” 和“figure-level” 无差异。

图形迭代、渲染

迭代:可定义一个基础图形,然后按需求在基础图形上绘制不同图形,不同图形之间相互独立,

#定义基础图形p
p = (
so.Plot(fmri, x="timepoint", y="signal", color="event")
.map_color(palette="crest")
)

p.add(so.Line()) #绘制折线图
p.add(so.Line(), group="subject")

与Matplotlib集成

“axes-level”容易实现,可直接对子图操作,

import matplotlib as mpl
_, ax = mpl.figure.Figure(constrained_layout=True).subplots(1, 2)
(
so.Plot(tips, x="total_bill", y="tip")
.on(ax)
.add(so.Scatter())
)

“figure-level”  比较难缠,

f = mpl.figure.Figure(constrained_layout=True)
(
so.Plot(tips, x="total_bill", y="tip")
.on(f)
.add(so.Scatter())
.facet("time")
)

subfigures让多子图更简单,

sf1, sf2 = f.subfigures(1, 2)
(
so.Plot(tips, x="total_bill", y="tip", color="day")
.add(so.Scatter())
.on(sf1)
.plot()
)
(
so.Plot(tips, x="total_bill", y="tip", color="day")
.facet("day", wrap=2)
.add(so.Scatter())
.on(sf2)
.plot()
)

小结

  • 如果该新版本发布, Seaborn老版本子图难实现、个性化难、需要重度依赖Matplotlib的缺陷基本被修复
  • 新版本吸收了ggplot2的部分属性,对R用户比较容易上手;

  • 但是, Seaborn支持图形类别有限 的问题没有看到修复;
  • 再者,到底啥时候新版本能够发布, This is very much a work in progress

  • 总之,非常值得期待。

  • ref: https://seaborn.pydata.org/nextgen/

近期文章

视频专栏课 | Python网络爬虫与文本分析

如何在DataFrame中使用If-Else条件语句创建新列

BERTopic 主题建模库 | 建议收藏

Top2Vec | 主题建模和语义搜索库

案例实战 | 企业信息数据采集

使用文本相似度可以识别变化的时间点

PNAS | 文本网络分析&文化桥梁Python代码实现

tomotopy | 速度最快的LDA主题模型

dvt | 视觉文化分析的Python工具包

Stargazer库 | 创建漂亮可发表的多元回归表

人文社科类Python免费教程列表

量化历史语言学-贝叶斯语言谱系分析

Python与文化分析入门

Backtrader库 | 均线买入卖出策略实现

读完本文你就了解什么是文本分析

文本分析在经管领域中的应用概述

综述:文本分析在市场营销研究中的应用

文本分析方法在《管理世界》(2021.5)中的应用

hiResearch 定义自己的科研首页

SciencePlots | 科研样式绘图库

Wow~70G上市公司定期报告数据集

漂亮~pandas可以无缝衔接Bokeh

YelpDaset: 酒店管理类数据集10+G