Python中的ggplot—plotnine模块可视化图册

介绍

R语言数据可视化的强大之处在于ggplot2,而plotnine就是python版的ggplot2,语法与R语言的ggplot2基本一致,无论是从语法简洁性、作图灵活性、美观度等方面,个人认为plotnine均可胜于python中那些常用的可视化模块(例如:matplotlib、seaborn等)。

目前国内在用plotnine的人似乎还不多,中文网站上很难搜索到比较全面的使用方法,作为数据分析工作者,出图的速度直接影响数据挖掘的效率,所以撰此文目的在于加强自己对可视化模块plotnine的学习巩固,同时也可以分享给正在学习可视化的同学。

初步计划持续更新五个系列图表绘制案例及N个真实的数据分析项目:

五个系列图表:趋势型图表、分布型图表、类别比较型图表、数据关系型图表、局部整体型图表

N个真实案例:分析案例均源自本人实际经手的数据项目,会持续更新,会做脱敏

最近更新时间:2022.05.22

快速通道↓↓↓

目录

介绍

准备

一、趋势型图表系列

1.1折线图

1.2面积图

1.3夹层填充面积图

1.4百分比堆积面积图

二、类别比较型图表系列

2.1单数据系列柱形图

补充:类别排序问题

 2.2多数据系列柱形图

补充:表降维处理

准备

模块安装、导入

pip install plotnine

from plotnine import *

汉字乱码问题解决

import matplotlib as plt

plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

一、趋势型图表系列

场景case:

某互联网公司为了提高裂变类活动的转化率,分别设计并同时上线了两种活动形式(A活动、B活动),通过对比AB两种活动的累计转化率,取较优者决策。

样本示例:

1.1折线图

Python中的ggplot—plotnine模块可视化图册

def plot_a_1(df):
    base_plot = (
        ggplot(df, aes(x='日期', y='转化率', group='分组', color='分组'))
        +geom_line(size=1)
        +scale_x_date(name='日期', breaks='2 weeks') #解决x轴标签覆盖问题
        +scale_fill_hue(s=0.90, l=0.65, h=0.0417, color_space='husl') #自动配色
        #若自定义线条颜色可将上一行代码替换为:
        #+scale_color_manual(values=('#084081', '#7bccc4'))
        #若在折线图上添加值标签可用下行代码(此图不建议添加值标签,不美观)
        #+geom_text(aes(x='日期',y='转化率',label='转化率'),color='black')
        +xlab('时间') #重命名x轴名称
        +ylab('CVR') #重命名y轴名称
        +ggtitle('AB组活动转化率趋势图')
        +theme_matplotlib()
    )
    print(base_plot)
    base_plot.save('page/趋势图/图a_1.jpeg', dpi=1000)

1.2面积图

Python中的ggplot—plotnine模块可视化图册

def plot_a_2(df):
    base_plot = (
        ggplot(df, aes(x='日期', y='转化率', group='分组'))
        +geom_area(aes(fill='分组'), alpha=0.75, position='identity')
        +geom_line(aes(color='分组'), size=0.75)
        +scale_x_date(name='日期', breaks='2 weeks') #解决x轴日期标签间隔、覆盖问题
        +scale_fill_hue(s=0.90, l=0.65, h=0.0417, color_space='husl')
        +xlab('时间')
        +ylab('CVR')
        +ggtitle('AB组活动转化率趋势图')
        +theme_matplotlib()
    )
    print(base_plot)
    base_plot.save('page/趋势图/图a_2.jpeg', dpi=1000)

1.3夹层填充面积图

Python中的ggplot—plotnine模块可视化图册

绘图前需要先对样本数据做一下处理,处理代码及处理后的dataframe如下:

def plot_a_3(df):
    df_A = df[df['分组'] == 'A组']
    df_B = df[df['分组'] == 'B组']
    df_new = pd.merge(df_A, df_B, how='left', on='日期', suffixes=('A组', 'B组'))
    df_new['最小值'] = df_new.apply(lambda x: x[['转化率A组', '转化率B组']].min(), axis=1)
    df_new['最大值'] = df_new.apply(lambda x: x[['转化率A组', '转化率B组']].max(), axis=1)
    #df_new['比较'] = df_new.apply(lambda x: 'A组高' if x['转化率A组'] - x['转化率B组'] > 0 else 'B组高', axis=1)
    df_new['ymin1'] = df_new['最小值']
    df_new.loc[(df_new['转化率A组']-df_new['转化率B组']) > 0, 'ymin1'] = np.nan
    df_new['ymin2'] = df_new['最小值']
    df_new.loc[(df_new['转化率A组']-df_new['转化率B组']) <= 0, 'ymin2'] = np.nan
    df_new['ymax1'] = df_new['最大值']
    df_new.loc[(df_new['转化率A组']-df_new['转化率B组']) > 0, 'ymax1'] = np.nan
    df_new['ymax2'] = df_new['最大值']
    df_new.loc[(df_new['转化率A组']-df_new['转化率B组']) <= 0, 'ymax2'] = np.nan

    
    base_plot=(
        ggplot()
        +geom_ribbon(df_new, aes(x='日期', ymin='ymin1', ymax='ymax1', group=1), alpha=0.5, fill='#00B2F6', color='none')
        +geom_ribbon(df_new, aes(x='日期', ymin='ymin2', ymax='ymax2', group=1), alpha=0.5, fill='#FF6B5E', color='none')
        +geom_line(df, aes(x='日期', y='转化率', group='分组', color='分组'), size=1)
        +scale_x_date(name='日期', breaks='2 weeks')
        +theme_matplotlib()
    )
    print(base_plot)

 

 做以上处理的目的是为作图做准备:

①最大值、最小值:用于绘制夹层的填充线;

②之所以ymin1/ymax1 与 ymin2/ymax2 区分开,是为了区分填充线颜色

③之所以绘制两次ribbon除了原因②之外,也是为了避免出现多余的填充

1.4百分比堆积面积图

场景case:

某互联网公司在全国城市推广了一种引流活动,并将城市划分了7个等级(一线、新一线、二线….其他),因为来自不同城市等级的用户质量不同,所以需要关注每个活动期次中用户来源的城市等级构成变化。

样本示例:

同一‘活动期次’中,‘同期占比’之和为1,虽然样本中有这一数据,但我们在绘图时不会用到”同期占比”,所以在实际绘图导入数据时无需计算该值。

 Python中的ggplot—plotnine模块可视化图册

def plot_a_4(df):
    base_plot = (
        ggplot(df, aes(x='活动期次', y='参与人数', fill='城市等级', group='城市等级'))
        +geom_area(position='fill', alpha=1)
        +geom_line(position='fill', size=0.25, color='black')
        +scale_fill_hue(s=0.99, l=0.65, h=0.0417, color_space='husl')
        +xlab('活动期次')
        +ylab('同期占比')
        +theme_matplotlib()
    )
    print(base_plot)
    base_plot.save('page/趋势图/图a_4.jpeg', dpi=1000)

 补充:与1.2面积图不同的是position参数的设置,‘identity’表示不改变位置,而‘fill’则表示在多数据系列时以百分比的形式堆叠(数量会自动转为占比后在y轴显示),另外比较常用的还有position=’stack’,意思是堆积,假如仅把上图position参数fill换成stack,那么输出如下:

Python中的ggplot—plotnine模块可视化图册

图解:例如第”1期”的y轴值约2500,该值表示所有城市等级用户数量之和。 

也就是说:每个系列的开始点是前一个数据系列的结束点,y轴的值表示多个系列的数值之和。

而假如,仅把上述代码中position参数换成identity,则输出如下:

此时y轴的值仅表示某一单个系列的数值。

Python中的ggplot—plotnine模块可视化图册

二、类别比较型图表系列

2.1单数据系列柱形图

Python中的ggplot—plotnine模块可视化图册

def plot_b_1():
    df = pd.DataFrame({'Cut': ['fair', 'good', 'very good', 'premium', 'ideal'], 'Price': [4300, 3800, 3950, 4700, 3500]})

    base_plot = (
        ggplot(df, aes(x='Cut', y='Price'))
        +geom_bar(stat='identity', width=0.8, colour='black', size=0.25, fill='#FF6B5E', alpha=1)
        +theme_matplotlib()
    )
    print(base_plot)
    base_plot.save('page/类别比较/图b_1_1.jpeg', dpi=1000)

补充:类别排序问题

绘制柱形图、条形图系列的最大潜在问题就是排序,

plotnine绘制柱形图时,X轴变量默认会按照输入的数据顺序绘制,若要调整顺序,需对dataframe的类别顺序进行调整(pandas.Categorical方法的使用),

假如要将上图的绘制顺序改为按”Price”的值降序排列,则代码为:

def plot_b_1():
    df = pd.DataFrame({'Cut': ['fair', 'good', 'very good', 'premium', 'ideal'], 'Price': [4300, 3800, 3950, 4700, 3500]})
    sort_df = df.sort_values(by='Price', ascending=False)
    sort_df['Cut'] = pd.Categorical(sort_df['Cut'],  categories=sort_df['Cut'], ordered=True)

    base_plot = (
        ggplot(sort_df, aes(x='Cut', y='Price'))
        +geom_bar(stat='identity', width=0.8, colour='black', size=0.25, fill='#FF6B5E', alpha=1)
        +theme_matplotlib()
    )
    print(base_plot)
    base_plot.save('page/类别比较/图b_1_2.jpeg', dpi=1000)

Python中的ggplot—plotnine模块可视化图册

若要自定义类别顺序,可以修改如下代码:

例如将顺序修改为 fair→premium→very good→ideal→good

df = pd.DataFrame({'Cut': ['fair', 'good', 'very good', 'premium', 'ideal'], 'Price': [4300, 3800, 3950, 4700, 3500]})

df['Cut'] = pd.Categorical(sort_df['Cut'],  categories=['fair','premium','very good','ideal','good'], ordered=True)

 2.2多数据系列柱形图

Python中的ggplot—plotnine模块可视化图册

def plot_b_2():
    df = pd.DataFrame({'Cut': ['fair', 'good', 'very good', 'premium', 'ideal'],
                       'Price_A': [4300, 3800, 3950, 4700, 3500],
                       'Price_B': [4000, 3200, 4300, 3700, 3000]})
    #做数据处理,目的是以Price_A的值降序绘制
    df = df.sort_values(by='Price_A', ascending=False)
    #原始数据是二维表,需要将其转化成一维表
    df_new = pd.melt(df, id_vars='Cut')
    df_new['Cut'] = pd.Categorical(df_new['Cut'], categories=df['Cut'])

    base_plot = (
        ggplot(df_new, aes(x='Cut', y='value', fill='variable'))
        +geom_bar(stat='identity', color='black', position='dodge', width=0.7, size=0.25)
        #dodge水平抖动放置、stack垂直堆叠放置、identity不做调整(多系列情况下会存在覆盖问题)、fill百分比堆叠
        +scale_fill_hue(s=0.90, l=0.65, h=0.0417, color_space='husl')
        #若自定义填充色
        #+scale_fill_manual(values=['#FF6B5E','#00B2F6'])
        +theme_matplotlib()
    )
    print(base_plot)
    base_plot.save('page/类别比较/图b_2.jpeg', dpi=1000)

补充:表降维处理

pandas.melt()方法

案例中原始及降维后的数据框如下:

原始:
         Cut  Price_A  Price_B
0       fair     4300     4000
1       good     3800     3200
2  very good     3950     4300
3    premium     4700     3700
4      ideal     3500     3000

降维处理后:
         Cut variable  value
0    premium  Price_A   4700
1       fair  Price_A   4300
2  very good  Price_A   3950
3       good  Price_A   3800
4      ideal  Price_A   3500
5    premium  Price_B   3700
6       fair  Price_B   4000
7  very good  Price_B   4300
8       good  Price_B   3200
9      ideal  Price_B   3000

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2022年5月23日
下一篇 2022年5月23日

相关推荐