【问题标题】:Repeat the last value over time随着时间的推移重复最后一个值
【发布时间】:2022-08-24 19:18:42
【问题描述】:

我有一张不同年份的发电厂容量表。只有当容量发生变化时才会有条目。在未列出的年份中,最后一个值适用。

Plant Year Capacity
Cottam 2003 800
Cottam 2009 600
Cottam 2015 800
Drax 2000 600
Drax 2005 1200
Drax 2010 1800
Drax 2013 1200
Drax 2020 0
Ironbridge 2007 500
Ironbridge 2015 0

现在我想转换初始表,以便我也有介于两者之间的所有年份的值,并且可以将它们显示在堆积柱形图中,例如。结果应如下表所示。黄色标记的是初始表格中的数字。

  • 这是一个数据塑造练习。您确定要 DAX 而不是 M/Power Query 吗? DAX 中的计算表可以工作吗?
  • 这当然是一个简化的示例,我将不得不看看如何将解决方案集成到我相当复杂的发电厂数据库中。我猜 DAX 也会起作用。
  • 罗恩的回答是正确的方法。

标签: powerbi dax interpolation


【解决方案1】:

您可以在 M 代码的查询编辑器中轻松完成此操作。

要重现,请将以下代码粘贴到空白查询中:

let

//change next line to reflect your actual data source
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45Wcs4vKUnMVdJRMjIwMAZSFgYGSrE6qOKWQMoMU9zQFEm9S1FiBUS1AZJqhChIraERurAhSLEhhhmGxlhVG4FUQ8Q8i/LzkooyU9JTIcabAylTA6xyYGcCZWIB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Plant = _t, Year = _t, Capacity = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Plant", type text}, {"Year", Int64.Type}, {"Capacity", Int64.Type}}),

//generate Table of all years
    #"All Years" = Table.FromColumns(
            {List.Numbers(List.Min(#"Changed Type"[Year]), List.Max(#"Changed Type"[Year])- List.Min(#"Changed Type"[Year]) + 1 )}),

//Group by Plant
// Aggregate by joining with the All Years table and "Fill Down" to replace blanks with previous year.
// then expand the grouped column
    #"Group by Plant" = Table.Group(#"Changed Type","Plant",{
        {"Joined", each Table.FillDown(Table.Join(#"All Years","Column1",_,"Year",JoinKind.FullOuter),{"Capacity"})}
    }),
    #"Expanded Joined" = Table.ExpandTableColumn(#"Group by Plant", "Joined", {"Column1", "Capacity"}, {"Column1", "Capacity"}),

//Replace nulls with zero's
    #"Replaced Value" = Table.ReplaceValue(#"Expanded Joined",null,0,Replacer.ReplaceValue,{"Capacity"}),

//Pivot on year
//  then set the data types
    #"Pivoted Column" = Table.Pivot(Table.TransformColumnTypes(#"Replaced Value", {{"Column1", type text}}, "en-US"), 
        List.Distinct(Table.TransformColumnTypes(#"Replaced Value", {{"Column1", type text}}, "en-US")[Column1]), "Column1", "Capacity"),

//set data type
    #"Changed Type1" = Table.TransformColumnTypes(#"Pivoted Column", 
        List.Transform(List.Sort(List.RemoveFirstN(Table.ColumnNames(#"Pivoted Column"),1), Order.Ascending), each {_, Int64.Type}))
in
    #"Changed Type1"

编辑说明:
实际上,要在 Power BI 中创建图表,您可以不是想要旋转数据,所以更短的代码:

let

//change next line to reflect your actual data source
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45Wcs4vKUnMVdJRMjIwMAZSFgYGSrE6qOKWQMoMU9zQFEm9S1FiBUS1AZJqhChIraERurAhSLEhhhmGxlhVG4FUQ8Q8i/LzkooyU9JTIcabAylTA6xyYGcCZWIB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Plant = _t, Year = _t, Capacity = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Plant", type text}, {"Year", Int64.Type}, {"Capacity", Int64.Type}}),

//generate Table of all years
    #"All Years" = Table.FromColumns(
            {List.Numbers(List.Min(#"Changed Type"[Year]), List.Max(#"Changed Type"[Year])- List.Min(#"Changed Type"[Year]) + 1 )}),

//Group by Plant
// Aggregate by joining with the All Years table and "Fill Down" to replace blanks with previous year.
// then expand the grouped column
    #"Group by Plant" = Table.Group(#"Changed Type","Plant",{
        {"Joined", each Table.FillDown(Table.Join(#"All Years","Column1",_,"Year",JoinKind.FullOuter),{"Capacity"})}
    }),
    #"Expanded Joined" = Table.ExpandTableColumn(#"Group by Plant", "Joined", {"Column1", "Capacity"}, {"Year", "Capacity"}),

//Replace nulls with zero's
    #"Replaced Value" = Table.ReplaceValue(#"Expanded Joined",null,0,Replacer.ReplaceValue,{"Capacity"}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Replaced Value",{{"Year", Int64.Type}, {"Capacity", Int64.Type}})
in
    #"Changed Type1"

然后,在 Power BI 中,您可以生成以下内容:

笔记:下面的代码展示了使用变量和更多 cmets 的第一个代码中的 Table FillDown / Table Join 序列。应该更容易理解(虽然可能效率较低)

...
{"Joined", each 
            let 
            //join the subtable with the All Years table
                #"Joined Table" = Table.Join(#"All Years", "Column1", _, "Year", JoinKind.FullOuter),

            //Fill down the Capacity column so as to fill with the "last year" data
            //   since that column will contain a null after the Table.Join for years with no data
                #"Fill Down" = Table.FillDown(#"Joined Table",{"Capacity"})
            in 
                #"Fill Down"
    }
...

【讨论】:

  • 我发现很难分解组合的 Group - Join - Filldown 步骤,因此我无法真正将您的示例解决方案应用于我更复杂的问题。
  • @彼得我不明白。但当然,不能代表真正问题的案例示例可能会导致对示例有效的解决方案,但不适用于真正的问题。
  • 不是我的意思。相反,看起来好像 group-fill-join 步骤是随后构建的,就像许多 Excel 用户将他们的中间公式复制到最后一个 - 可能是为了节省空间。然而,这使得这些结果难以理解和在必要时进行调整。
  • @Peter不,它是这样构造的。但是从内部到外部的公式。在各种论坛上,我观察到大多数知识渊博的贡献者似乎都避免使用变量,所以我只是复制它们,除非事情非常复杂。我将编辑问题以包含该部分的细分并发表评论。
【解决方案2】:

以下是如何解决这个问题(更容易)达克斯

  1. 先决条件是单独的日历具有 1:many 关系的表
    Calendar = 
    SELECTCOLUMNS(
       GENERATESERIES(
           MIN(Plants[Year]),
           MAX(Plants[Year])
       ),
       "Year", [Value]
    )
    
    1. 接下来计算最后给定容量每年
    Last Given Capacity = 
    VAR current_year = 
        MAX(Calendar[Year])
    VAR last_capacity_year =
        CALCULATE(
            MAX(Plants[Year]),
            'Calendar'[Year] <= current_year
        )
    RETURN
        CALCULATE(
            MAX(Plants[Capacity]),
            Calendar[Year] = last_capacity_year
        )
    
    1. 最后把它们放在一起堆积柱形图
    X-axis: 'Calendar'[Year]
    Y-axis: [Last Given Capacity]
    Legend: 'Plants'[Plant]
    

【讨论】:

    猜你喜欢
    • 2018-09-10
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    相关资源
    最近更新 更多