本文蕴藏杀机,PowerBI DAX 设计的诸多精华尽在一个模型,推荐仔细阅读。上篇文章写得少得可怜,很多战友提出严重抗议,要求继续揭示这其中的奥秘,好吧,你吩咐,我照办。
先看效果吧:
下面详细解读。
自从2018.5《PowerBI 全动态 RFM 模型 1.0》发布以及2019.6《PowerBI 全动态 RFM 模型 2.0》发布,收到强烈反响,并收到很多战友的反馈。集中表现在:
- 要求再强调一下核心理念
- 要求再解释下 2.X 版的重大更新
- 指出了内藏的业务逻辑优化问题
因此,我们今天发布 2.2 版,并简单解释战友提出的问题。
首先给出2.2版本的样子,如下:
与其对照的 2.0(2.1)版本,如下:
从展现来说,是没有任何差异的,而其实却做了非常多的优化,让我们一起来欣赏这个过程。
核心理念
关于什么是RFM,这里就不再介绍,可以参考1.0版的文章或自行搜索相关概念,这里不再赘述。要强调的是:在PowerBI中实现RFM模型,可以充分利用DAX计算的动态性,根据用户的选择实时做出计算,这与完全交给IT计算或在纯Excel中计算都不同。
- 完全交给IT计算,往往是固定不变的逻辑,由IT使用SQL等底层数据库技术完成;
- 完全在Excel中计算,则计算的能力有限,以及配套的可视化有限。
在 PowerBI 中使用 DAX 计算,则完全由分析师完成,它可以平衡灵活性和计算能力。这在全动态 ABC 模型中也有一样的效果。
对照上图,我们指出这里的一些已有亮点。
动态计算类别后再筛选
这个特性太凶残了,如果你看懂了,那就真正理解到DAX的精华了,如下:
以及:
首先,任意客户的RFM分类并不是预先存在的,而是要动态实时计算的;熟悉DAX数据模型的人都知道只有预先存在的模型中的列才能筛选与之相关的表;而这里,我们完全破除了这个限制,让动态计算完的元素可以被继续筛选,这种动态中的动态,可以称之为连环动态筛选,非常残忍。
三维转二维的全动态
我们都知道RFM模型的示意图是这样的:
而在PowerBI中是没有这种3D空间型可视化的,即使有,也很难标记各种元素,因此,我们做了一个有意义的转换:
- 取RFM中任意两个指标,分别作为X,Y;
- 取RFM中剩余的指标,作为大小;
- 再用元素本身的RFM分类绘制颜色。
这样,就可以绘制散点图,如下:
这里采用了X对应于R,而Y对应于F,M自然对应于点的大小,并绘制颜色。注意上面的标题是动态的,可以显示各个坐标轴和点的含义。
如果反选X,Y轴,其表现为:
当然,我们可以用R,M来表示X,Y,将得到:
反选后,又将得到:
好神奇啊,当然,还可以使用F,M表示X,Y,则有:
反选后,又将得到:
换言之,这里将3D的信息,充分投影到2D空间,投影的方式完全自定,相当地残酷。
我知道你有好奇心,就是想选个特别的,来满足你,看吧:
如果你将X,Y选择成一样的,标题会动态地提示你这是错误的。
这样的3D转2D,这样的颜色分类,这样的任意选择,这样的温馨提示,堪称完美得无懈可击,有点凶残。
如果你认为这算炫技,我们也绝不否认,这就是在炫技,但还没有结束。
日期区间的动态性
首先,这并不是对全局所有时间进行计算,而是针对分析人员所选的日期区间进行计算,如下:
这点就是商业智能完全碾压传统SQL的地方,这种计算是实时指定的,而不是预先指定,每指定一次,去SQL查询一次。
M指标KPI的动态性
到底用什么来指定一个客户的M指标呢,是销售额,利润还是购买数量,抑或是利润率,写SQL没法知道这种动态性,而在商业智能中,PowerBI却可以让用户实时指定,有点残忍了。
R算法的动态性
R在RFM中表示最近的购买指标,到底怎么算最近呢,我们可以用若干个月来界定,也可以用其他的日期计算方式来界定,这个地方就是用来给出这种可能性,让我们知道我们不会被限制,我们来看看不同指定方式的效果差异。
首先来看看固定的10个月区间法,效果如下:
由于按月数计算,离散度很大,所以所有的点都会聚集到某些整数得分上,这是一种非常简单快速的划分方式。再来看看按照实际日期长度的划分,效果是:
可以看出,这就立刻表现出了交叠的连续性。使用哪种形态可以完全由分析师动态决定了,有点凶猛的。
客户的可搜索性
这里还充分考虑了由于客户很多,我们就是想知道某个特定客户的分类归属,我们可以直接搜索,如下:
这样非常方便地提供了查找客户的能力。
客户的动态计算范围
细心的伙伴可以发现,这里的计算范围也是可以动态设定的,例如:
如果按照全局计算,那客户白婵是一般保持客户,即使过滤到只剩她一个也如此,如下:
但此时如果选择【按所选客户】计算,则会出现:
既然是按所选范围计算,那么,只有一个人的时候,就相当于在这个人是计算范围,自然就只能是重要价值客户,我们可以多选几个来看,如下:
由于多选,重新按照这个所选范围计算,客户的分类就改变了。值得注意的是,全局的分布如下:
可以看出平均值F=25正好是上述两个客户的平均值,而非四个客户,因为有两个客户不符合参与FRM计算的条件而被排除。天呢,太灵活了,太可怕了。怎么可能精细地控制到这个Level。
精雕细琢 臻于完美
如果您认为这就算结束,那就错了,我们看到:
自然可以提出,希望可以在图中标出不同的客户,因为此时只有少数几个点,我们已经准备了【显示标签】按钮,点击即可,效果如下:
点的标签显示出来,同时按钮呈现【隐藏标签】字样,意思说还可以隐藏标签,是的,如果标签过多,就会是这样:
这是无法辨识的,因此需要点击【隐藏标签】来隐藏所有标签,如下:
太人性化了,太残暴了,如此雕琢,如同打造一件奢侈品。如果您认为这就结束了,那就又大错特错了。
到此,一切才刚刚开始。
2.X 重大更新
从 2.0 版本,往后都称为 2.X 版。目前当前版本为 2.2 版,目前认为是该模型的稳定版。在该版本中,我们主要更新了三个方面:
- 利用了PowerBI及DAX的最新能力,如:动态染色,动态标题等。
- 更新了设计模式。
- 平衡了灵活性与性能。
具体说来,在设计模式方面,这里借鉴了软件工程中 MVC 设计模式以及 依赖注入 设计思想,尤其是2.2中对此有重要体现,如下:
RFM模型包括三个度量值文件夹:
- Core,盛放RFM核心框架业务逻辑,属于不需要改变的部分。
- View,盛放视图层的计算逻辑,与业务无关,实现动态染色或建立可视化。
- 依赖注入,盛放RFM各分量的实际业务计算逻辑。
值得说明的是,这三个文件夹几乎是任何通用了标准模型的标配,因为模型的通用性,必然存在一个框架性的业务逻辑;而实际的逻辑是以实际为准的,则必然由依赖注入完成;逻辑的最终体现通常是可视化,而在PowerBI中的报表层,则是DAX驱动的,因此,具有View。
重要业务逻辑优化及完备性
有战友提出了一个非常有价值的问题:该模型的计算是否可以只针对老客户进行? 当时我们给了实现的建议,由于该建议的合理性和重要性,这里给出标准实现以供参考。
业务逻辑的合理性论证
将原子计算指定为用于老用户,这具有非常重要的现实意义,对于所选区间的新用户是不存在RFM的。因此,准确地讲,RFM是对老客户进行分类的进一步方法。也就是说,对于对客户的分类法,可以认为:
- 首先,将客户分为新客户和老客户;
- 其次,再将老客户按RFM分为8种类型分别运营。
整个运营逻辑结构如下:
从运营的角度看,重复购买几乎被认定为商业模式是否成功的必要判断标准,因此,合理有效的老客户就非常重要,而对于不同类型的老客户需要采取的运营策略和资源又会不同,因此,RFM几乎是一种自然而然地标准分类法则,而这应该是基于老客户进行的。
DAX 设计与实现
因此,这里对 RFM 的核心逻辑植入这一业务逻辑,其核心业务逻辑如下:
- 对于所选的日期区间,计算其中的老客户集合;
- 对于任意其中的老客户,实施RFM分类及计算。
DAX如下:
VAR OldCustomers = FILTER( VALUES( 'Order'[客户ID] ) , CALCULATE( MIN( 'Order'[订单日期] ) , ALL( 'Model.Date' ) ) < MIN( 'Model.Date'[Date] ) )
RETURN
IF( SELECTEDVALUE( User[客户ID] ) IN OldCustomers ,
< 真正的计算逻辑 >
)
其中,<真正的计算逻辑>
由依赖注入给出,这也是充分体验设计模式的地方。在实际的实现中,则是:
RFM.Item.M =
VAR OldCustomers = FILTER( VALUES( 'Order'[客户ID] ) , CALCULATE( MIN( 'Order'[订单日期] ) , ALL( 'Model.Date' ) ) < MIN( 'Model.Date'[Date] ) )
RETURN IF( SELECTEDVALUE( User[客户ID] ) IN OldCustomers , [RFM.Item.M.Action] )
其中,依赖注入项为[RFM.Item.M.Action]
,其实现为:
RFM.Item.M.Action =
[KPI.Auto] / MAXX( ALL( User[客户名称] ) , [KPI.Auto] ) * 100
而全局平局的值则为:
RFM.Aver.M =
AVERAGEX( ALLSELECTED( User[客户名称] ) , [RFM.Item.M] )
因此,整个逻辑就非常清晰了。
设计的巧妙之处
确实出现了非常细心的战友伙伴,问道,如果一个人没有销售记录,出现空值,如何处理?在计算整体平均时,是否考虑出现空值的客户?
由于核心的业务逻辑框架改用了老客户版本,那么当前日期区间必然存在购买记录,否则就不是老客户了。而对于不是老客户的人,其RFM得分也是空。最巧妙地计算就在于整体平均计算会忽略这些空值,使得整个计算结果是合理有效的。
这种巧妙地设计要精通DAX的每个细节,因为这些计算上的巧合使得整个模型多一寸嫌多,少一寸嫌少,刚刚好的感觉很棒。
RFM 模型的完备性
一般在数学领域会用完备性来描述一个框架的完整性,而该模型就满足一种完备性。
经过上述的调整,我们得到了无懈可击的完美RFM模型如下:
Core,实现了RFM的核心逻辑:
- 分别计算任意元素的R,F,M分量值;
- 分别计算任意元素的R,F,M分量分类;
- 分别计算整体的R,F,M均值;
- 计算任意元素的RFM分类;
- 计算任意元素的RFM分类颜色;
- 计算任意元素的RFM定量加权总计;
- 计算在不同RFM分类下的客户数;
其中,R,F,M分量的计算由依赖注入项(度量值)给出。
整个逻辑框架,完美得无懈可击,太凶残了,多一个嫌多,少一个嫌少,刚刚好。
灵活与性能的平衡
这样的完美模型,怎能不去平衡下性能呢,其实为了保持性能,我们并没有将模型的动态性发挥到极致。这也不断在向伙伴们展示,在我们可以驾驭任意级别的动态性之后,我们仍然可以自如的回退到一个平衡的位置,为什么没有2.0.0版,其实伙伴们直接拿到的2.1版,本次发布的是2.2版,这是因为2.0版的设计考虑了极致的动态性,导致核心散点图计算需要15秒,而完全优化后达到了0.8秒,当然,2.2版由于加入了少许复杂的计算,性能略有下降,我们实测结果如下:
可以这么归纳:
- 极致动态,牺牲性能 需15秒
- 平衡动态,平衡性能 需0.8秒
- 进阶动态,合理性能 需1.8秒
合理可接受,因此,我们最终采用这一版本。
总结
整体说来,RFM模型整体如下:
整体设计采用MVC设计模式,并通过依赖注入提供灵活扩展,并采用了规范化的命名系统。
最终形成效果:
该模型设计在八个维度下全量动态计算,模型同时兼具了业务能力强,逻辑严密、灵活扩展、性能强大,展现精巧,设计规范,精致细节等特色,是非常经典的商业智能范例,也是目前世界范围内最强大的(没有之一)PowerBI DAX RFM 商业智能案例实现。充分展示了PowerBI及DAX的能力,毫不夸大地说,这是无懈可击的完美模型,该 RFM2.2 模型 既可以直接套用,又特别适合用来研习PowerBI及DAX的精华,对于PowerBI用户来说,是绝对不可错过的,希望大家可以照此练习,建议对照1.0版,2.1版,2.2版学习,您会看到一个模型是如何一步步从初始状态优化成为一个无懈可击的完美模型。也欢迎战友伙伴们提出更多好的想法,优化是永无止境的。周末又到了,战友们,尽情享用吧。