我应该如何定义 DAX 度量以按时间序列视觉对象中的类别规范化数据集值?

How should I define a DAX measure to normalize dataset values by category in a time series visual?

我正在尝试按类别获取值图,归一化为 最早日期的类别值不早于时间切片器中的选定日期。

我尝试了以下 DAX 度量:

Normalized = 
    var mintime = CALCULATE(min(Data[Date]), ALLSELECTED(Data))
    var initial = SUMX(FILTER(ALLSELECTED(Data), Data[Date]=mintime), Data[Value])
    return DIVIDE(SUM(Data[Value]), initial)

但这无法正确计算每个类别的初始值,相应地,图表上的线不是从 1 开始的。 例如,使用示例数据集 Data 定义为:

      Date Category  Value
2022-01-01        A    100
2022-01-01        B     95
2022-01-02        A     60
2022-01-02        B    115
2022-01-02        C     95
2022-01-03        A     36
2022-01-03        B     34
2022-01-03        C     54
2022-01-04        A     22
2022-01-04        B     10
2022-01-04        C     27

我得到以下不正确的情节:

我应该如何修改我的度量以获得正确的结果?

作为参考,我知道我可以在每个类别的计算表中分离数据:

TableA = FILTER(Data, Data[Category] == "A")
TableB = FILTER(Data, Data[Category] == "B")
TableC = FILTER(Data, Data[Category] == "C")

然后为每个类别定义单独的 DAX 度量:

A = 
    var mintime = CALCULATE(min(TableA[Date]), ALLSELECTED(TableA))
    var initial = SUMX(FILTER(ALLSELECTED(TableA), TableA[Date]=mintime), TableA[Value])
    return DIVIDE(SUM(TableA[Value]), initial)
B = ...

连同保持所有 TableA[Date]TableB[Date]、... 的关系以引用共同的时基。 将这些措施中的每一个堆叠成一个线图确实产生了预期的结果:

然而,随着类别数量的增加(我的生产数据集确实有更多类别),这很快变得相当不切实际。 因此,我正在寻找一种涉及单个度量的替代方法,并根据情节图例进行上下文化。

这个问题原来与ALLSELECTED的效果有关 带有 table 参数的 CALCULATE 修饰符,带有列参数或 作为 table 函数。 有关更多信息,可以找到关于该主题的非常详细的讨论 in this blog on www.sqlbi.com.

计算类别的最早日期

计算mintimeALLSELECTED(Data)的用法为

var mintime = CALCULATE(min(Data[Date]), ALLSELECTED(Data))

是一个带有 table 参数的 CALCULATE 修饰符。 ALLSELECTED 的行为然后解析为显式过滤器 CALCULATE 表达式。 由于在这种情况下唯一明确的过滤器是页面的时间滑块,那是 唯一应用的过滤。 这导致变量 mintime 保持最短时间 类别(仅受滑块影响),与适用类别无关。

另一方面,使用 ALLSELECTEDData[Date] 列参数 将使用在测量时创建的隐式类别过滤器 评估遍历日期(以及页面上的任何显式过滤器)。 因此,要获得给定类别值中的最早日期, 应使用以下内容:

var mintime = CALCULATE(MIN(Data[Date]), ALLSELECTED(Data[Date]))

计算类别最早日期的初始值

同理,ALLSELECTED(Data)在计算initial时的用法

var mintime = CALCULATE(MIN(Data[Date]), ALLSELECTED(Data))
var initial = SUMX(FILTER(ALLSELECTED(Data), Data[Date]=mintime), Data[Value])

是一个 table 函数,它只会导致显式滑块过滤器成为 应用。这给出了一个 initial 值,它是所有类别的总和。 要保留隐式过滤器,我们应该考虑使用 Data[Date] 列 而是争论。然而,在这个表达式中,这也会减少可用的数据集 SUMX 函数,使 Data[Value] 引用无效。 为了解决这个问题,我们可以分两步重写表达式:首先 根据日期筛选数据,然后使用 CALCULATE 计算 对应值:

var initial = CALCULATE(SUM(Data[Value]), FILTER(ALL(Data[Date]),Data[Date]=mintime))

此时我们应该注意,使用ALLALLSELECTED作为table函数 在 FILTER 上下文中产生相同的结果,因为实际过滤 类别出现在外部 CALCULATE 循环中。 这将我们带到更短的等价形式(如 here 所示):

var initial = CALCULATE(SUM(Data[Value]), Data[Date]=mintime)

结论

要获得正确的结果,可以按如下方式修改度量:

Normalized = 
    var mintime = CALCULATE(MIN(Data[Date]), ALLSELECTED(Data[Date]))
    var initial = CALCULATE(SUM(Data[Value]), Data[Date]=mintime)
    return DIVIDE(SUM(Data[Value]),initial)