如何在Power Query中按Process分组计算相邻行数值差值?
需求说明
我是Power Query / BI新手,现有如下示例数据表:
| DateTime | Process | Activity | ElapsedProcessTime(s) | TimeInterval(s) (预期输出) |
|---|---|---|---|---|
| 17/Jul/2024 00:00:00 | A | 1 | 0 | 0 |
| 17/Jul/2024 00:10:00 | A | 2 | 600 | 600 |
| 17/Jul/2024 00:15:01 | A | 3 | 901 | 301 |
| 17/Jul/2024 00:15:45 | A | 4 | 945 | 44 |
| 17/Jul/2024 01:00:00 | B | 1 | 0 | 0 |
| 17/Jul/2024 01:10:00 | B | 2 | 600 | 600 |
| 17/Jul/2024 01:15:01 | B | 3 | 901 | 301 |
| 17/Jul/2024 01:15:45 | B | 4 | 945 | 44 |
| 17/Jul/2024 14:00:00 | C | 1 | 0 | 0 |
| 17/Jul/2024 14:05:00 | C | 2 | 300 | 300 |
| 17/Jul/2024 14:15:01 | C | 3 | 901 | 601 |
| 17/Jul/2024 14:15:55 | C | 4 | 955 | 54 |
需要编写Power Query公式计算**TimeInterval(s)**列:当前行与同Process组内前一行的ElapsedProcessTime(s)差值,Process切换时重置为0。
解决方案
步骤1:确保数据排序正确
先按Process和DateTime列排序,保证每个Process内的行按时间顺序排列:
- 选中
Process列,点击「排序升序」 - 按住Ctrl选中
DateTime列,点击「排序升序」
步骤2:按Process分组处理
- 点击「转换」选项卡 → 「分组依据」
- 在弹出窗口中设置:
- 分组依据:
Process - 新列名:
GroupedData - 操作:「所有行」
- 点击确定
- 分组依据:
步骤3:添加自定义列计算差值
- 选中
GroupedData列,点击「添加列」→ 「自定义列」 - 输入以下公式:
let ElapsedList = Table.Column([GroupedData], "ElapsedProcessTime(s)"), PrevList = {0} & List.RemoveLastN(ElapsedList, 1), IntervalList = List.Transform(List.Zip({ElapsedList, PrevList}), each _{0} - _{1}), AddedColumn = Table.FromColumns(Table.ToColumns([GroupedData]) & {IntervalList}, Table.ColumnNames([GroupedData]) & {"TimeInterval(s)"}) in AddedColumn
- 将新列命名为
WithInterval,点击确定
步骤4:展开最终数据表
点击WithInterval列的展开箭头,选择所有需要保留的列(DateTime、Activity、ElapsedProcessTime(s)、TimeInterval(s)),点击确定即可得到结果。
完整M代码示例
假设你的原始数据源名为Source,完整代码如下:
let Source = 你的数据源, // 排序数据 Sorted = Table.Sort(Source,{{"Process", Order.Ascending}, {"DateTime", Order.Ascending}}), // 按Process分组 Grouped = Table.Group(Sorted, {"Process"}, {{"GroupedData", each _, type table [DateTime=datetime, Process=text, Activity=number, ElapsedProcessTime(s)=number]}}), // 计算TimeInterval列 AddedInterval = Table.AddColumn(Grouped, "WithInterval", (g) => let ElapsedList = Table.Column(g[GroupedData], "ElapsedProcessTime(s)"), PrevList = {0} & List.RemoveLastN(ElapsedList, 1), IntervalList = List.Transform(List.Zip({ElapsedList, PrevList}), each _{0} - _{1}), AddedColumn = Table.FromColumns(Table.ToColumns(g[GroupedData]) & {IntervalList}, Table.ColumnNames(g[GroupedData]) & {"TimeInterval(s)"}) in AddedColumn ), // 展开数据表 Expanded = Table.ExpandTableColumn(AddedInterval, "WithInterval", {"DateTime", "Activity", "ElapsedProcessTime(s)", "TimeInterval(s)"}) in Expanded
内容的提问来源于stack exchange,提问作者Mr Tea
相关产品推荐
相关产品推荐

