原文链接:http://juzicode.com/python-module-plotnine/
plotnine 是Python中基于R语言ggplot移植的图形可视化库,采用分层语法理念,通过叠加图形元素构建复杂图表,强调数据与视觉属性的映射关系。
应用场景
- 结构化图形构建
- 学术论文图表制作
- 多维数据探索
- 定制化统计图形
- 数据故事叙述
安装与导入
pip install plotnine
from plotnine import *
使用方法
1)散点图与趋势线
展示汽车排量与油耗关系,添加回归趋势线。
# juzicode.com/VX公众号:juzicode
import matplotlib.pyplot as plt
from plotnine import *
import pandas as pd
import numpy as np
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False # 解决负号乱码
# 生成数据
np.random.seed(1)
data = pd.DataFrame({
'wt': np.random.normal(3.2, 0.8, 50),
'mpg': 35 - 5*np.random.normal(3.2, 0.8, 50) + np.random.randn(50)*2
})
# 绘制图形并指定字体
plot = (
ggplot(data, aes(x='wt', y='mpg'))
+ geom_point(color='steelblue', size=3)
+ geom_smooth(method='lm', color='firebrick')
+ labs(title='汽车重量与油耗关系', x='重量(吨)', y='油耗(英里/加仑)')
+ theme(text=element_text(family='SimHei')) # 确保 plotnine 使用中文字体
)
# 显示或保存图形
plot.draw()
plot.save("1.png", dpi=300)

2)分面直方图
按汽车气缸数分面显示马力分布。
# juzicode.com/VX公众号:juzicode
import matplotlib.pyplot as plt
from plotnine import *
import pandas as pd
import numpy as np
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
# 生成不同气缸数的马力数据
np.random.seed(2)
data = pd.DataFrame({
'cyl': np.repeat([4, 6, 8], [20, 15, 15]),
'hp': np.concatenate([
np.random.normal(90, 10, 20),
np.random.normal(120, 15, 15),
np.random.normal(180, 20, 15)
])
})
# 绘制图形并指定字体
plot = (
ggplot(data, aes(x='hp'))
+ geom_histogram(binwidth=15, fill='skyblue', color='navy')
+ facet_wrap('~cyl', ncol=3)
+ labs(title='不同气缸数马力分布', x='马力', y='计数')
+ theme(text=element_text(family='SimHei')) # 确保 plotnine 使用中文字体
)
# 显示或保存图形
plot.draw()
plot.save("2.png", dpi=300)

3)箱线图与抖动点
按变速箱类型分组展示油耗分布。
# juzicode.com/VX公众号:juzicode
import matplotlib.pyplot as plt
from plotnine import *
import pandas as pd
import numpy as np
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
# 成变速箱类型数据
np.random.seed(3)
data = pd.DataFrame({
'am': np.repeat([0, 1], 25),
'mpg': np.concatenate([
np.random.normal(18, 2, 25),
np.random.normal(24, 3, 25)
])
})
# 绘制图形并指定字体
plot = (
ggplot(data, aes(x='factor(am)', y='mpg'))
+ geom_boxplot(fill='bisque')
+ geom_jitter(width=0.1, color='tomato')
+ scale_x_discrete(labels=['自动', '手动'])
+ labs(title='变速箱类型与油耗关系', x='变速箱类型', y='油耗')
+ theme(text=element_text(family='SimHei'))
)
# 显示或保存图形
plot.draw()
plot.save("3.png", dpi=300)

4)密度曲线矩阵
绘制鸢尾花特征密度曲线分面图。
# juzicode.com/VX公众号:juzicode
import matplotlib.pyplot as plt
from plotnine import *
import pandas as pd
import numpy as np
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
# 生成鸢尾花模拟数据
np.random.seed(4)
species = ['setosa', 'versicolor', 'virginica']
data = pd.DataFrame({
'species': np.repeat(species, 50),
'sepal_length': np.concatenate([
np.random.normal(5.0, 0.5, 50),
np.random.normal(5.9, 0.6, 50),
np.random.normal(6.5, 0.7, 50)
])
})
# 绘制图形并指定字体
plot = (
ggplot(data, aes(x='sepal_length', fill='species'))
+ geom_density(alpha=0.6)
+ facet_grid('species ~ .')
+ labs(title='萼片长度分布', x='萼片长度(cm)')
+ theme(legend_position='none', text=element_text(family='SimHei'))
)
# 显示或保存图形
plot.draw()
plot.save("4.png", dpi=300)

5)热力图绘制
可视化汽车特征相关性矩阵。
# juzicode.com/VX公众号:juzicode
import matplotlib.pyplot as plt
from plotnine import *
import pandas as pd
import numpy as np
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
# 生成相关矩阵数据
np.random.seed(5)
features = ['mpg', 'cyl', 'disp', 'hp']
corr = pd.DataFrame(
np.random.uniform(-0.9, 0.9, (4, 4)),
columns=features,
index=features
)
corr = (corr + corr.T)/2 # 确保对称
np.fill_diagonal(corr.values, 1)
corr = corr.reset_index().melt(id_vars='index')
# 绘制图形并指定字体
plot = (
ggplot(corr, aes(x='index', y='variable', fill='value'))
+ geom_tile()
+ scale_fill_gradient2(low='blue', high='red')
+ labs(title='特征相关性', x='', y='')
+ theme(axis_text_x=element_text(angle=45), text=element_text(family='SimHei'))
)
# 显示或保存图形
plot.draw()
plot.save("5.png", dpi=300)

6)时间序列可视化
绘制股票价格趋势带置信区间。
# juzicode.com/VX公众号:juzicode
import matplotlib.pyplot as plt
from plotnine import *
import pandas as pd
import numpy as np
plt.rcParams["font.family"] = "SimHei"
plt.rcParams["axes.unicode_minus"] = False
# 生成时间序列数据
np.random.seed(6)
dates = pd.date_range('2000-01-01', periods=120, freq='M')
data = pd.DataFrame({
'date': dates,
'unemploy': 8000 + np.cumsum(np.random.randn(120)*100)
})
# 绘制图形并指定字体
plot = (
ggplot(data, aes(x='date', y='unemploy'))
+ geom_line(color='slategray')
+ geom_ribbon(aes(ymin='unemploy-500', ymax='unemploy+500'), alpha=0.2)
+ labs(title='失业率变化趋势', x='日期', y='失业人数(千)')
+ scale_x_date(date_breaks='2 years', date_labels='%Y')
+ theme(text=element_text(family='SimHei'))
)
# 显示或保存图形
plot.draw()
plot.save("6.png", dpi=300)

进阶技巧
- 主题定制:使用theme()调整网格、字体等细节样式
- 图层叠加:灵活组合+运算符添加多个几何对象
- 映射系统:利用aes()实现动态视觉编码
- 统计变换:结合stat_function()实现自定义统计图形
总结
plotnine的核心优势:
- 直观的图形语法体系
- 高度模块化的图层结构
- 优雅的默认主题风格
- 强大的分面系统
注意事项:
- 颜色映射需显式指定scale
- 中文支持需额外配置字体参数