在 Power BI 中使用周历

原创:      2025-01-22 14:09

本文翻译自Marco Russo & Alberto Ferrari的文章—《Using weekly calendars in Power BI》来源:SQLBI本文阐述了基于周的日历(如4-4-5周制)对特定行业的重要性,以及如何在 Power BI 中有效地使用它们。


截至2024年10月,Power BI没有内置功能来管理基于周的日历。现有的开箱即用功能(自动日期/时间)基于标准的公历创建一个日期表,每年包含12个月和365天或366天。然而,逐月比较数据意味着要比较工作日数量不同的月份。

许多企业的许多指标都强烈依赖于工作日和周末的数量。在这种情况下,通常使用基于周的另一种日历:每个时期(如月、季度或年)都汇总完整的周,从而不与底层的公历对齐,但每个时期的工作日数量保持一致。本文探讨了当进行同比比较时,这两种技术(基于月和基于周)之间的差异,并介绍了实现这些技术的工具。

制造业、零售业以及对周末或工作日数量敏感的任何企业都普遍使用周历。例如,本文描述的场景使用了2019年至2024年间某网站的页面浏览量数据,数据截至2024年9月3日。所分析的网站呈现出明显的周趋势,周末流量较慢,如下面的每日粒度折线图所示。这似乎是一个商业网站。而体育网站可能会显示出相反的趋势。


以周为粒度的相同数据更容易看出长期趋势和异常情况的影响。


以月为粒度时,趋势看起来更加平滑。然而,每个月工作日的数量不同可能会导致一些细微的差异。


当我们比较按公历月份分组和按ISO 4-4-5周历分组的页面浏览量的同比百分比差异(YOY%)时,这些差异更加明显。例如,2024年4月的增长率在公历中被夸大了,显示为13.45%,而按周历计算的增长率虽然不错但较低,为6.62%。


在本文中,我们探索和回顾了在Power BI中构建报告以使用周而不是日历月作为基本比较单位来比较数据的选项。

与自动日期/时间的月度比较

我们分析的模型很简单。我们只看从CSV文件导入的一个表格,该表格有三列:日期、客户端和页面浏览量。客户端列描述了传入流量的类型(是由机器人产生还是由网页浏览器产生)。


通过启用自动日期/时间功能,我们获得了一个通过日期层次结构显示的隐藏日期表。


隐藏的日期表无法进行自定义,并且不提供按周的任何聚合。与上一年的比较可以在DAX中使用SAMEPERIODLASTYEAR函数来实现,该函数使用列变体语法pageviews[Date].[Date]来获取日期列的引用:

页面浏览量表中的度量

# Pageviews YOY % =VAR _Current = [# Pageviews]VAR _Previous = CALCULATE ( [# Pageviews], SAMEPERIODLASTYEAR ( 'pageviews'[Date].[Date] ) )VAR _Difference = _Current - _PreviousVAR Result = DIVIDE ( _Difference, _Previous )RETURN IF ( NOT ISBLANK( _Previous ) && NOT ISBLANK( _Current ), Result )


四月总是有30天。然而,我们正在比较2024年4月(有22个工作日)与2023年4月(只有20个工作日)的价值——由于复活节落在不同的日子,这可能会影响比较结果。


除了我们稍后会描述的使用52周偏移量进行的可能比较之外,您无法使用Power BI自动生成的日期表创建基于每周的图表或矩阵。

获取一个免费的日期表

在创建基于周的日期表之前,我们想先介绍一下如何获取一个可以自定义的日期表。Bravo for Power BI是一个免费的开源外部工具,它可以使用许多可用的可配置模式之一来创建一个计算日期表。


文件“Pageviews – Gregorian Calendar.pbix”包含由Bravo创建的日期表。所获得的月度结果与使用“自动日期/时间”功能时所见的结果相同。但是,当模型中存在一个以上的日期列(无论是在同一个表中还是在不同的表中)时,我们需要一个单独的日期表。我们使用的示例模型包含一个表和一个日期列。不过,Bravo还会在所选度量值上创建我们所需的所有时间智能计算。


Bravo添加的度量值被嵌套在特定的文件夹中,并且可以通过使用搜索框轻松找到。


这是Bravo为支持“同比%#浏览量”度量值而自动生成的DAX代码:

页面浏览量表中的度量

YOY % # Pageviews =DIVIDE (
    [YOY # Pageviews],
    [PY # Pageviews])


页面浏览量表中的度量

YOY # Pageviews =VAR __ValueCurrentPeriod = [# Pageviews]VAR __ValuePreviousPeriod = [PY # Pageviews]VAR __Result =    IF (
        NOT ISBLANK ( __ValueCurrentPeriod ) && NOT ISBLANK ( __ValuePreviousPeriod ),
        __ValueCurrentPeriod - __ValuePreviousPeriod
    )RETURN
    __Result


页面浏览量表中的度量

PY # Pageviews =IF (
    [_ShowValueForDates],
    CALCULATE (
        [# Pageviews],
        CALCULATETABLE (
            DATEADD ( 'Date'[Date], -1, YEAR ),            'Date'[DateWithTransactions] = TRUE
        )
    )
)


然而,使用不同的模板,Bravo可以根据周来创建一个不同的日期表。

实施基于ISO(4-4-5)周的日历

当我们想要按周分析数据时,首要挑战是一个月并非一组完整的周。一周可能跨越两个不同的月份。因此,为了比较不同时间段,存在多种技术来创建周的聚合。

一种广泛使用且有多种变化的方法是基于52周的年度定义。这样,一年总是有364天,可以分成四个季度,每个季度13周,即91天。每个季度有三个时间段,每个时间段有4周或5周。每个季度的时间段顺序相同,因此可能的组合是4-4-5、4-5-4和5-4-4。例如,在4-4-5周历中,每个季度的前两个时间段始终是4周,最后一个时间段始终是5周。

我们更倾向于使用“时间段”这一术语,因为在基于周的日历中,“月份”与公历月份并不对应。例如,2023年的第一季度在公历中有90天,而在4-4-5周历中有91天。我们以其中最具代表性的月份来命名这些时间段。例如,第一个时间段被称为1月,主要是因为它大部分包含1月的天数。但这并非完全匹配。你会看到,在4-4-5周历中,每个时间段都是以该时间段内最具代表性的月份命名的,所以在这个例子中,1月和2月共28天,3月35天。月份列中使用的“FM”前缀代表“财政月”,因为基础时间段与公历月份的天数不匹配!


“2022年的最后一天是2023年1月1日”这一说法是错误的,应改为“2022年的最后一天是12月31日,而2023年的第一天是1月1日”。接下来是翻译后的内容:

2022年的最后一天是12月31日,而2023年的第一天是1月1日。“2023年财政二月(FM February 2023)”的第一天是2023年1月30日,所以2月的最后两天属于“2023年财政三月(FM March 2023)”。然而,这种混淆只因为我们使用了与公历相同的月份名称。重要的是,每个季度的第一个时间段的天数、周数和工作日数都相同,这使得在不同季度和年份之间进行比较变得容易。

同样地,4-4-5周历中的季度也与公历中的季度不匹配。


为了使周历与公历对齐,每6-7年,最后一个季度的最后一个时间段会增加一周,从而形成4-4-6、5-4-5或4-5-5的组合。然而,尽管没有标准化的做法,但在进行比较时,这一额外的一周可以被忽略。

使用Bravo,我们只需点击几下即可获得一个支持基于周的日历的日期表。以下配置支持在4-4-5周历中遵循ISO-8601标准的周编号。但是,您可以选择不同的参数集以符合您公司所采用的标准。例如,美国公司通常将星期日作为一周的第一天,并可能使用不同的设置来定义一年的最后一个工作日。


Bravo还会为所选模板创建时间智能度量。例如,这是“同比%#页面浏览量”度量的定义:

页面浏览量表中的度量


YOY % # Pageviews =DIVIDE (
    [YOY # Pageviews],
    [PY # Pageviews])


页面浏览量表中的度量


YOY # Pageviews =VAR __ValueCurrentPeriod = [# Pageviews]VAR __ValuePreviousPeriod = [PY # Pageviews]VAR __Result =    IF (
        NOT ISBLANK ( __ValueCurrentPeriod ) && NOT ISBLANK ( __ValuePreviousPeriod ),
        __ValueCurrentPeriod - __ValuePreviousPeriod
    )RETURN
    __Result


页面浏览量表中的度量


PY # Pageviews =IF (
    [_ShowValueForDates],
    SUMX (        VALUES ( 'Date'[Fiscal Year Number] ),        VAR __CurrentFiscalYearNumber = 'Date'[Fiscal Year Number]        VAR __DaysSelected =
            CALCULATETABLE (                VALUES ( 'Date'[Day of Fiscal Year Number] ),
                REMOVEFILTERS ( 'Date'[Day of Week Number], 'Date'[Day of Week] ),                'Date'[DateWithTransactions] = TRUE
            )        RETURN
            CALCULATE (
                [# Pageviews],
                'Date'[Fiscal Year Number] = __CurrentFiscalYearNumber - 1,
                __DaysSelected,
                ALLEXCEPT ( 'Date', 'Date'[Day of Week Number], 'Date'[Day of Week] )
            )
    )
)


PY (#Pageviews) 通过选择上一财年中相同的相对日期来应用筛选器。关于如何在基于周的日历上实现时间智能计算的技术的完整描述,可以在 www.daxpatterns.com 上的“与周相关的计算模式”中找到。

2024年4月的计算汇总了28天,因为这是在4-4-5日历中的一个季度的第一个时段。同比 (# Pageviews) 百分比比较了2024年4月1日至28日与2023年4月3日至30日的数据,这两个时间段的工作日数量相同。


然而,按周工作并不适用于需要我们根据公历月份总和提供数字的场景。一些公司使用公历年内的周数,并接受在年初或年末可能会有一周被截断的情况。但是,在这些场景中,按周比较永远不会与按月和按季度的汇总混合使用。为了避免这种情况,另一种方法是:严格将周用于比较,而不是用于报告。

以52周为周期的同比比较

使用基于周的日历产生的年度总和通常与公司的财年不一致。实际上,财年通常与公历中的整月相吻合。例如,许多公司的财年都是从某个月的第一天开始,如1月1日或7月1日。每年都应该从月份中的同一天开始,这是使用标准的DAX时间智能函数的要求,因为这些函数不支持从不同日期开始的年份。

虽然使用4-4-5日历年可以方便地比较不同时段,但4-4-5日历年与公司的财年之间的不匹配可能会造成误解。因此,一种将两者结合起来的可能方法是,在进行任何同比比较时,使用52周的偏移量。实际上,通过从选定时段中减去364天(相当于52周),我们可以得到前一年相同的天数和工作日数。这种方法不需要在几年后额外增加第53周,因为你仍然在使用标准的公历。然而,如果按这种方式计算,前一年的值将不会与在公历中查看前一年值时所得到的值相匹配。使用这种方法时,2023年1月1日(星期日)至2023年12月31日(星期日)的范围将与2022年1月2日(星期日)至2023年1月1日(星期日)的范围进行比较。同样的日期,即2023年1月1日,出现在两个被比较的时段中!这似乎有悖直觉……但它确实有效!

此时,一个例子可能会有所帮助。让我们从公历开始。我们使用DATEADD函数减去52周来实现同比计算,这将导致364天的偏移:

页面浏览量表中的度量

YOY % 52W =VAR _Current = [# Pageviews]VAR _Previous = CALCULATE ( [# Pageviews], DATEADD ( 'Date'[Date], -52*7, DAY ) )VAR _Difference = _Current - _PreviousVAR Result = DIVIDE ( _Difference, _Previous )RETURN IF ( NOT ISBLANK( _Previous ) && NOT ISBLANK( _Current ), Result )


我们可以使用公历比较两种同比增长率(YOY%)的计算结果。2024年4月的同比增长率为8.52%。这比将2024年4月与2023年4月(两者的工作日天数不同)进行比较所得的13.45%要低得多。52周的同比增长率(YOY % 52W)指标使用2023年4月3日至2023年5月2日作为2024年4月的比较期。这样,当前期和前期都从周一开始,30天后在周二结束,且工作日天数相同。


52周的同比增长率(YOY % 52W)返回的值更接近使用每周4-4-5日历计算的同比增长率(YOY%)。然而,我们无法比较这两份报告,因为在使用周历的情况下,起点(如2024年4月财务月,FM表示财务月)与公历中使用的日历月不同。事实上,如果我们将52周的同比增长率指标应用于4-4-5日历,那么在有52周的所有年份中,我们会看到与按周计算的同比增长率(# Pageviews表示的YOY%)相同的结果。


只要一年有52周,这两种比较方式都会得出相同的结果。然而,在2020财年,我们有53周,这就是为什么按年计算的同比百分比与次年(2021财年)所有计算的结果存在差异,这些差异源于额外的第53周。


如果你使用的是基于周的日历,你可能会更倾向于使用Bravo生成的时间智能计算。然而,52周偏移量是一种方便的技术,也可以与公历一起使用,以便在不需要与会计账簿的数字相匹配且没有周历可用时,进行更好的比较。

结论

在商业中,周历常用于比较具有相同工作日数和星期数的时间段。Power BI不直接支持这种日历。但是,你可以轻松地为Power BI中的Bravo创建一个基于周的日历,该日历还会添加相应的周时间智能计算。

当使用公历进行比较时,一个很好的权宜之计是使用52周偏移量来检索相应的时间段。虽然所使用的数字与会计账簿中的数字不匹配,但这种方法可以应用于现有的语义模型,而不会破坏现有的计算和报告。


客户案例

按行业 按部门

线上课程

课程直通 讲师介绍

官方微信

联系我们

北京

13811982114
agileex@agileex.com

北京市朝阳区博雅国际中心A座601

上海

13811982114
agileex@agileex.com

上海市静安区沪太路453号302室

Copyright © 2022 北京敏捷艾科数据技术有限公司agileex.com - 京ICP备16008845号-1