pyecharts
pyecharts有漏斗图的模板(点击链接),套用即可。
代码
from pyecharts import options as opts
from pyecharts.charts import Funnel
data = [135043, 113413, 74909, 10366, 9018, 4151]
phase = ['总访客数量 ', '活跃访客数量', '注册用户数量', '预定用户数量', '支付用户数量', '复购用户数量']
c = (
Funnel()
.add("阶段", [list(z) for z in zip(phase, data)])
.set_global_opts(title_opts=opts.TitleOpts(title="漏斗图"))
.render("funnel.html")
)
图片
虽然绘制方便,但是美观程度一般。
matplotlib
使用matplotlib绘制的思路是,绘制两个横向柱状图,其中一个设置成背景色遮住另一个的部分柱长,再绘制多边形填充两个柱子之间的间隔。
代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.patches import Polygon # Polygon()可以用来传入按顺序组织的多边形顶点,从而生成出多边形
from matplotlib.collections import PatchCollection
plt.style.use('seaborn-dark') # 设置主题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
visitor_num = 135043
data = [135043, 113413, 74909, 10366, 9018, 4151]
phase = ['总访客数量 ', '活跃访客数量', '注册用户数量', '预定用户数量', '支付用户数量', '复购用户数量']
data1 = [visitor_num/2 - i/2 for i in data]
data2 = [i+j for i,j in zip(data, data1)]
color_list = [ '#5c1d1d', '#892c2c','#994a4a', '#c56161', '#d48989', '#e2b0b0'] # 柱子颜色
fig,ax = plt.subplots(figsize=(16, 9),facecolor='#f4f4f4')
ax.barh(phase[::-1], data2[::-1], color = color_list, height=0.7) # 柱宽设置为0.7
ax.barh(phase[::-1], data1[::-1], color = '#f4f4f4', height=0.7) # 设置成背景同色
ax.axis('off')
polygons = []
for i in range(len(data)):
# 阶段
ax.text(
0, # 坐标
i, # 高度
phase[::-1][i], # 文本
color='black', alpha=0.8, size=16, ha="right")
# 数量
ax.text(
data2[0] / 2 ,
i,
str(data[::-1][i]) +'(' +str(round(data[::-1][i] / data[0] * 100, 1)) + '%)',
color='black', alpha=0.8, size=18, ha="center")
if i < 5:
# 比例
ax.text(
data2[0] / 2 ,
4.4 - i,
str(round(data[i+1] / data[i], 3) * 100) + '%',
color='black', alpha=0.8, size=16, ha="center")
# 绘制多边形
polygons.append(Polygon(xy=np.array([(data1[i+1], 4+0.35-i), # 因为柱状图的宽度设置成了0.7,所以一半便是0.35
(data2[i+1], 4+0.35-i),
(data2[i], 5-0.35-i),
(data1[i], 5-0.35-i)])))
# 使用add_collection与PatchCollection来向Axes上添加多边形
ax.add_collection(PatchCollection(polygons,
facecolor='#e2b0b0',
alpha=0.8));
plt.show()
图片
ploty
2021-09-22更新 最近接触到ploty,发现有现成的库,较为美观,遂更新下文章,出处(https://plotly.com/python/funnel-charts/)。
基础漏斗图
import plotly.express as px
data = dict(
number=[39, 27.4, 20.6, 11, 2],
stage=["Website visit", "Downloads", "Potential customers", "Requested price", "invoice sent"])
fig = px.funnel(data, x='number', y='stage')
fig.show()
堆积漏斗图
import plotly.express as px
import pandas as pd
stages = ["Website visit", "Downloads", "Potential customers", "Requested price", "invoice sent"]
df_mtl = pd.DataFrame(dict(number=[39, 27.4, 20.6, 11, 3], stage=stages))
df_mtl['office'] = 'Montreal'
df_toronto = pd.DataFrame(dict(number=[52, 36, 18, 14, 5], stage=stages))
df_toronto['office'] = 'Toronto'
df = pd.concat([df_mtl, df_toronto], axis=0)
fig = px.funnel(df, x='number', y='stage', color='office')
fig.show()
带有各项指标的漏斗图
from plotly import graph_objects as go
fig = go.Figure(go.Funnel(
y = ["Website visit", "Downloads", "Potential customers", "Requested price", "invoice sent"],
x = [39, 27.4, 20.6, 11, 2]))
fig.show()
鼠标悬浮在图上可以看到当前阶段的各项占比
漏斗图自定义颜色
from plotly import graph_objects as go
fig = go.Figure(go.Funnel(
y = ["Website visit", "Downloads", "Potential customers", "Requested price", "Finalized"],
x = [39, 27.4, 20.6, 11, 2],
textposition = "inside",
textinfo = "value+percent initial",
opacity = 0.65, marker = {"color": ["deepskyblue", "lightsalmon", "tan", "teal", "silver"],
"line": {"width": [4, 2, 2, 3, 1, 1], "color": ["wheat", "wheat", "blue", "wheat", "wheat"]}},
connector = {"line": {"color": "royalblue", "dash": "dot", "width": 3}})
)
fig.show()
带有各项指标的堆积漏斗图
from plotly import graph_objects as go
fig = go.Figure()
fig.add_trace(go.Funnel(
name = 'Montreal',
y = ["Website visit", "Downloads", "Potential customers", "Requested price"],
x = [120, 60, 30, 20],
textinfo = "value+percent initial"))
fig.add_trace(go.Funnel(
name = 'Toronto',
orientation = "h",
y = ["Website visit", "Downloads", "Potential customers", "Requested price", "invoice sent"],
x = [100, 60, 40, 30, 20],
textposition = "inside",
textinfo = "value+percent previous"))
fig.add_trace(go.Funnel(
name = 'Vancouver',
orientation = "h",
y = ["Website visit", "Downloads", "Potential customers", "Requested price", "invoice sent", "Finalized"],
x = [90, 70, 50, 30, 10, 5],
textposition = "outside",
textinfo = "value+percent total"))
fig.show()