Python轮子:plotnine~数据可视化ggplot2的Python实现

原文链接: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
  • 中文支持需额外配置字体参数

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注