Power BI - 采用多列年份和值列并合并为仅 2 列

Posted

技术标签:

【中文标题】Power BI - 采用多列年份和值列并合并为仅 2 列【英文标题】:Power BI - Take Multiple Column Pairs of Year and Value Columns and Merge into just 2 Columns 【发布时间】:2019-08-05 17:38:01 【问题描述】:

我正在尝试以更可用的格式获取我的数据。我有以下列。

Donor     2019 Date  2019 Amt  2018 Date  2018 Amt  2017 Date  2017 Amt
--------  ---------  --------  ---------  --------  ---------  --------
Person 1  1/15/2019    100.00  4/20/2018     75.00  NULL           0.00 
Person 2  NULL           0.00  7/15/2018     50.00  NULL           0.00
Person 3  2/21/2019     50.00  3/03/2018     50.00  2/28/2017     50.00

这个数据实际上可以追溯到 2010 年。

我想达到的是:

Donor     Date       Amt
--------  ---------  ------
Person 1  1/15/2019  100.00
Person 1  4/20/2018   75.00
Person 2  7/15/2018   50.00
Person 3  2/21/2019   50.00
Person 3  3/03/2018   50.00
Person 3  3/28/2017   50.00

我玩过一些数据的反透视,但没有什么让我感到厌烦的就是让我得到我想要的东西。我认为可能需要进行一些转换才能完全满足我的需要。

【问题讨论】:

aldertalexis Olsen 都有正确答案。 Alexis Olson 答案对我来说只是更少的代码,并且至少是 1/2 动态的! 【参考方案1】:

你可以用两个反透视和一个过滤器来做到这一点:

选择所有年份日期列并取消透视,然后选择所有年份金额列并取消透视。最后,过滤到这些年份匹配的行。

完整的 M 码:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCkgtKs7PUzBU0lEy1Dc01TcyMLQEsQ0MgKQJkAsSsQCyzU2BBBAZKMXqwLUZwcSA8lDdILWmBljUGgMFjPSNDGFWgBUZ6xujaAIqsAAJmEMEYmMB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Donor = _t, #"2019 Date" = _t, #"2019 Amt" = _t, #"2018 Date" = _t, #"2018 Amt" = _t, #"2017 Date" = _t, #"2017 Amt" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,"Donor", type text, "2019 Date", type date, "2019 Amt", Int64.Type, "2018 Date", type date, "2018 Amt", Int64.Type, "2017 Date", type date, "2017 Amt", Int64.Type),
    #"Unpivoted Year Date" = Table.Unpivot(#"Changed Type", "2019 Date", "2018 Date", "2017 Date", "Year Date", "Date"),
    #"Unpivoted Year Amt" = Table.Unpivot(#"Unpivoted Year Date", "2019 Amt", "2018 Amt", "2017 Amt", "Year Amt", "Amt"),
    #"Match Years Filter" = Table.SelectRows(#"Unpivoted Year Amt", each Text.Start([Year Date], 4) = Text.Start([Year Amt], 4))
in
    #"Match Years Filter"

如果你有很多列,这个解决方案应该更方便。


使用Table.ColumnNames 使用一点 M 代码魔法,您可以像这样使其完全动态化:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCkgtKs7PUzBU0lEy1Dc01TcyMLQEsQ0MgKQJkAsSsQCyzU2BBBAZKMXqwLUZwcSA8lDdILWmBljUGgMFjPSNDGFWgBUZ6xujaAIqsAAJmEMEYmMB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Donor = _t, #"2019 Date" = _t, #"2019 Amt" = _t, #"2018 Date" = _t, #"2018 Amt" = _t, #"2017 Date" = _t, #"2017 Amt" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,"Donor", type text, "2019 Date", type date, "2019 Amt", Int64.Type, "2018 Date", type date, "2018 Amt", Int64.Type, "2017 Date", type date, "2017 Amt", Int64.Type),
    #"Unpivoted Year Date" = Table.Unpivot(#"Changed Type", List.Select(Table.ColumnNames(#"Changed Type"), each Text.EndsWith(_, " Date")), "Year Date", "Date"),
    #"Unpivoted Year Amt" = Table.Unpivot(#"Unpivoted Year Date", List.Select(Table.ColumnNames(#"Changed Type"), each Text.EndsWith(_, " Amt")), "Year Amt", "Amt"),
    #"Match Years Filter" = Table.SelectRows(#"Unpivoted Year Amt", each Text.Start([Year Date], 4) = Text.Start([Year Amt], 4))
in
    #"Match Years Filter"

这部分

List.Select(Table.ColumnNames(#"Changed Type"), each Text.EndsWith(_, " Amt"))

获取所有列名并挑选出以" Amt" 结尾的列。

【讨论】:

【参考方案2】:

你可以使用下面的 m-query

let
    Source = Csv.Document(File.Contents("C:\....\Documents\Pivot.csv"),[Delimiter=",", Columns=7, Encoding=1252, QuoteStyle=QuoteStyle.None]),
    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers","Donor", type text, "2019 Date", type text, "2019 Amt", type number, "2018 Date", type text, "2018 Amt", type number, "2017 Date", type text, "2017 Amt", type number),
    #"Data2019" = Table.SelectColumns(#"Changed Type","Donor", "2019 Date", "2019 Amt"),
    #"Renamed2019" = Table.RenameColumns(#"Data2019","2019 Date", "Date", "2019 Amt", "Value"),
    #"Data2018" = Table.SelectColumns(#"Changed Type","Donor", "2018 Date", "2018 Amt"),
    #"Renamed2018" = Table.RenameColumns(#"Data2018","2018 Date", "Date", "2018 Amt", "Value"),
    #"Data2017" = Table.SelectColumns(#"Changed Type","Donor", "2017 Date", "2017 Amt"),
    #"Renamed2017" = Table.RenameColumns(#"Data2017","2017 Date", "Date", "2017 Amt", "Value"),
    #"UnionAll" = Table.Combine(#"Renamed2017", #"Renamed2018", #"Renamed2019"),
    #"Filtered Rows" = Table.SelectRows(UnionAll, each ([Date] <> "NULL"))
in
    #"Filtered Rows"

它将选择列到 3 个不同的表中,然后我将它们组合在一起。这不是动态的意思是当你有额外的一年时,它不会相应地调整。

【讨论】:

以上是关于Power BI - 采用多列年份和值列并合并为仅 2 列的主要内容,如果未能解决你的问题,请参考以下文章

power bi 矩阵中的自定义聚合列

Power BI 多列排序问题

如何将多列合并为一列并使用自定义字符串格式化?

Power Query中如何把多列数据合并?

Power BI DAX CountIF 查询

Power BI笔记(一)