PowerBI 全網(wǎng)首發(fā)原生平滑曲線 - 原理及實現(xiàn)

僅以本文致敬本科的數(shù)學(xué)老師們,終于用上了一招。
大家都知道,Power BI 的折線圖并沒有平滑的曲線,這在很多時候非常不方便。
本文來探討 Power BI 中原生平滑曲線的實現(xiàn)。這要借助一些成熟的數(shù)學(xué)算法,我們并不打算研究這些數(shù)學(xué)算法的具體細節(jié),而是僅僅給出 DAX 實現(xiàn)以及對比。
效果
假設(shè)先有一個折線如下:

該折線的問題就是看著太生硬,我們希望它可以更加平滑。得到如下效果:

對于生硬的紅色折線,我們希望它可以變得平滑,如藍線所示。
那么問題來了:
如何從紅色折線得到藍色光滑曲線
如何確保藍色線是連續(xù)光滑的
如何確保藍色線的生成方式是通用的
為此,我們需要研究從獨立散點到形成光滑曲線的方法。
插值算法
我們研究了數(shù)學(xué)中的幾種插值算法,所謂插值,顧名思義,就是在已知的的點之間,插入一些新的值,在連線后,形成整條曲線。我們希望這條曲線滿足:
連續(xù)性
最速接近
高性能
我們考察了數(shù)學(xué)中的幾種算法,如下:

其中,紫色的 Cubic.Pro 和粉色的 Hermite 是重合的。
可以看出:粉色線是同時滿足三個條件的最佳算法。
算法實現(xiàn)
由于 Cubic.Pro 和 Hermite 算法默認重合,這里僅僅使用 Cubic.Pro 算法。
對于某個維度 X ,其每個點可由度量值計算出相應(yīng)的值。
所謂插值,就是將維度 X 的每兩個點之間插入新的節(jié)點,可以插入 1 ~ 1000 個點都可以。
而不難猜測,插入的點越多,越平滑,但計算量也越大。
例如:
插入 3 個點時:

很明顯,在彎折處是不夠光滑的。
插入 10 個點時:

已經(jīng)很光滑,但在細節(jié)處,我們放大看:

還是不夠光滑。
插入 20 個點時:

此時已經(jīng)非常光滑。
這樣,我們就得到了從點圖(折線圖)到完美的光滑曲線的最佳實踐,為:
采用 Cubic.Pro 插值算法
將原來的兩個點中插入 20 個點進行插值計算
滿足連續(xù)性以及光滑
性能沒有問題
DAX實現(xiàn)
第一步,對已有坐標(biāo)軸進行擴展,如下:
Axis.Ex =
VAR _n = 20 // 用于區(qū)間內(nèi)分割的點數(shù)
RETURN
FILTER(
GENERATEALL(
VALUES( 'Axis.X'[X] ) ,
SELECTCOLUMNS( GENERATESERIES( 0 , _n - 1 ) , "X'" , [X] + [Value] / _n )
),
[X'] <= MAX( 'Axis.X'[X] ) // 去除超過原區(qū)間大小的點
)第二步,實現(xiàn) Cubic.Pro 插值算法,如下:
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] 為原有維度坐標(biāo)軸
[Axis.Y.Sample] 為默認度量值
不要問這個算法的具體細節(jié)是什么意思,它需要應(yīng)用數(shù)學(xué)專業(yè)大二水準(zhǔn),這就是數(shù)學(xué)的用處。只需要記住這么用就行。
來對比下不同版本的 DAX 實現(xiàn)效果,如下:

我們選擇了 Cubic.Pro 算法以及 DAX 實現(xiàn),并完美的解決了利用 Power BI 原生折線生成光滑曲線的問題。
總結(jié)
雖然我們完美地實現(xiàn)了 Power BI 的光滑曲線,但:
有人會說,他 3 秒就可以在 Excel 里實現(xiàn)。
那么,他很厲害,他會用 Excel 點按鈕。
的確,Power BI 是不完美的,我們僅僅是在 Power BI 還不夠完美的過程中在用自己的方式來彌補 Power BI 的缺陷,這個彌補的過程看似非常愚蠢,非常無意義,但反而體現(xiàn)了我們在選擇一件工具最核心能力后的妥協(xié)和折衷。
如果這個世界存在完美,并讓人可以 3 秒爽,那么,是不是有點快得沒有意思了?
對于欠缺舉一反三能力的伙伴會問以下兩個問題:
我的坐標(biāo)軸不是 1,2,3 啊,而是產(chǎn)品,或日期,或用戶,如何做成平滑曲線呢?
如果元素非常多,例如,365 個日期,插值后會形成 3650 個點,運算量提升 20 倍,會不會有問題呢?
這個問題留作思考題。我們會在下篇文章來分享這兩個問題的優(yōu)化方法。
在 BI佐羅 出品的《BI真經(jīng)》的《PBI高級》中發(fā)布的通用視圖層算法將作為主要優(yōu)化手段。極力推薦要學(xué)習(xí) Power BI 的伙伴趕快訂購這一頂級教程,超越所有沒學(xué)該課程的 Power BI 用戶(本文就是又一例證)。
在訂閱了BI佐羅講授的《BI真經(jīng)》之《BI進行時》課程區(qū),除了可以下載本文案例,還可以觀看視頻講解。

讓數(shù)據(jù)真正成為你的力量
Create value?through?simple and?easy?with fun?by PowerBI
Excel BI?|?DAX Pro?|?DAX?權(quán)威指南?|?線下VIP學(xué)習(xí)
掃碼與PBI精英一起學(xué)習(xí),驗證碼:data2021
