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)