前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PowerBI 全网首发原生平滑曲线 - 原理及实现

PowerBI 全网首发原生平滑曲线 - 原理及实现

作者头像
BI佐罗
发布2021-02-08 21:09:48
1.6K0
发布2021-02-08 21:09:48
举报
文章被收录于专栏:PowerBI战友联盟PowerBI战友联盟

仅以本文致敬本科的数学老师们,终于用上了一招。

大家都知道,Power BI 的折线图并没有平滑的曲线,这在很多时候非常不方便。

本文来探讨 Power BI 中原生平滑曲线的实现。这要借助一些成熟的数学算法,我们并不打算研究这些数学算法的具体细节,而是仅仅给出 DAX 实现以及对比。

效果

假设先有一个折线如下:

该折线的问题就是看着太生硬,我们希望它可以更加平滑。得到如下效果:

对于生硬的红色折线,我们希望它可以变得平滑,如蓝线所示。

那么问题来了:

  • 如何从红色折线得到蓝色光滑曲线
  • 如何确保蓝色线是连续光滑的
  • 如何确保蓝色线的生成方式是通用的

为此,我们需要研究从独立散点到形成光滑曲线的方法。

插值算法

我们研究了数学中的几种插值算法,所谓插值,顾名思义,就是在已知的的点之间,插入一些新的值,在连线后,形成整条曲线。我们希望这条曲线满足:

  • 连续性
  • 最速接近
  • 高性能

我们考察了数学中的几种算法,如下:

其中,紫色的 Cubic.Pro 和粉色的 Hermite 是重合的。

可以看出:粉色线是同时满足三个条件的最佳算法。

算法实现

由于 Cubic.Pro 和 Hermite 算法默认重合,这里仅仅使用 Cubic.Pro 算法。

对于某个维度 X ,其每个点可由度量值计算出相应的值。

所谓插值,就是将维度 X 的每两个点之间插入新的节点,可以插入 1 ~ 1000 个点都可以。

而不难猜测,插入的点越多,越平滑,但计算量也越大。

例如:

插入 3 个点时:

很明显,在弯折处是不够光滑的。

插入 10 个点时:

已经很光滑,但在细节处,我们放大看:

还是不够光滑。

插入 20 个点时:

此时已经非常光滑。

这样,我们就得到了从点图(折线图)到完美的光滑曲线的最佳实践,为:

  • 采用 Cubic.Pro 插值算法
  • 将原来的两个点中插入 20 个点进行插值计算
  • 满足连续性以及光滑
  • 性能没有问题

DAX实现

第一步,对已有坐标轴进行扩展,如下:

代码语言:javascript
复制
Axis.Ex = 
VAR _n = 20 // 用于区间内分割的点数
RETURN
FILTER(
    GENERATEALL(
        VALUES( 'Axis.X'[X] ) ,
        SELECTCOLUMNS( GENERATESERIES( 0 , _n - 1 ) , "X'" , [X] + [Value] / _n )
    ),
    [X'] <= MAX( 'Axis.X'[X] ) // 去除超过原区间大小的点
)

第二步,实现 Cubic.Pro 插值算法,如下:

代码语言:javascript
复制
Axis.Y.Smooth.Cubic.Pro = 

VAR _y_min = CALCULATE( [Axis.Y.Sample] , TREATAS( { MIN( 'Axis.X'[X] ) } , 'Axis.X'[X] ) )
VAR _y_max = CALCULATE( [Axis.Y.Sample] , TREATAS( { MAX( 'Axis.X'[X] ) } , 'Axis.X'[X] ) )

VAR _y0 = COALESCE( CALCULATE( [Axis.Y.Sample] , TREATAS( { VALUES( 'Axis.Ex'[X] ) - 1 } , 'Axis.X'[X] ) ) , _y_min )
VAR _y1 = CALCULATE( [Axis.Y.Sample] , TREATAS( { VALUES( 'Axis.Ex'[X] ) + 0 } , 'Axis.X'[X] ) )
VAR _y2 = CALCULATE( [Axis.Y.Sample] , TREATAS( { VALUES( 'Axis.Ex'[X] ) + 1 } , 'Axis.X'[X] ) )
VAR _y3 = COALESCE( CALCULATE( [Axis.Y.Sample] , TREATAS( { VALUES( 'Axis.Ex'[X] ) + 2 } , 'Axis.X'[X] ) ) , _y_max )

VAR _dx = SELECTEDVALUE( 'Axis.Ex'[X'] ) - SELECTEDVALUE( 'Axis.Ex'[X] )

RETURN

    VAR _u1 = _dx
    VAR _u2 = _dx * _dx
    VAR _a0 = -0.5 * _y0 + 1.5 * _y1 - 1.5 * _y2 + 0.5 * _y3 
    VAR _a1 = _y0 - 2.5 * _y1 + 2 * _y2 - 0.5 * _y3
    VAR _a2 = -0.5 * _y0 + 0.5 * _y2
    VAR _a3 = _y1

    RETURN _a0 * _u1 * _u2 + _a1 * _u2 + _a2 * _u1 + _a3

其中,

  • 'Axis.X'[X] 为原有维度坐标轴
  • [Axis.Y.Sample] 为默认度量值

不要问这个算法的具体细节是什么意思,它需要应用数学专业大二水准,这就是数学的用处。只需要记住这么用就行。

来对比下不同版本的 DAX 实现效果,如下:

我们选择了 Cubic.Pro 算法以及 DAX 实现,并完美的解决了利用 Power BI 原生折线生成光滑曲线的问题。

总结

虽然我们完美地实现了 Power BI 的光滑曲线,但:

  • 有人会说,他 3 秒就可以在 Excel 里实现。

那么,他很厉害,他会用 Excel 点按钮。

的确,Power BI 是不完美的,我们仅仅是在 Power BI 还不够完美的过程中在用自己的方式来弥补 Power BI 的缺陷,这个弥补的过程看似非常愚蠢,非常无意义,但反而体现了我们在选择一件工具最核心能力后的妥协和折衷。

如果这个世界存在完美,并让人可以 3 秒爽,那么,是不是有点快得没有意思了?

对于欠缺举一反三能力的伙伴会问以下两个问题:

  • 我的坐标轴不是 1,2,3 啊,而是产品,或日期,或用户,如何做成平滑曲线呢?
  • 如果元素非常多,例如,365 个日期,插值后会形成 3650 个点,运算量提升 20 倍,会不会有问题呢?

这个问题留作思考题。我们会在下篇文章来分享这两个问题的优化方法。

在 BI佐罗 出品的《BI真经》的《PBI高级》中发布的通用视图层算法将作为主要优化手段。极力推荐要学习 Power BI 的伙伴赶快订购这一顶级教程,超越所有没学该课程的 Power BI 用户(本文就是又一例证)。

在订阅了BI佐罗讲授的《BI真经》之《BI进行时》课程区,除了可以下载本文案例,还可以观看视频讲解。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PowerBI战友联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 效果
  • 插值算法
  • 算法实现
  • DAX实现
  • 总结
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档