如何解决此代码,以计算每行多列重复项?

时间:2019-06-19 03:23:10

标签: powerquery

需要帮助修复此代码,以便计算当前行中多行和多列的重复次数。

这是我能想到的最简单的

Table.AddColumn(Source, "Add",
each List.Count(
Table.SelectRows(
    Source,
    (C) => List.Intersect(Table.ToList(Source),C(Table.ToList(Source)))=5
)[Column1]
))

它具有以下错误-

Expression.Error: We cannot convert a value of type Record to type Function.
Details:
    Value=Record
    Type=Type

以下是样本代表数据:

+---------+---------+---------+---------+---------+---------+----------------+--------------------+
| Column1 | Column2 | Column3 | Column4 | Column5 | Column6 | Count of Dup 5 | Comments           |
+---------+---------+---------+---------+---------+---------+----------------+--------------------+
|       1 |      12 |      17 |      25 |      27 |      39 |              2 | -row line 1 and 2  |
|       1 |      12 |      17 |      25 |      27 |      44 |              2 | -row line 1 and 2  |
|      98 |      99 |     100 |     101 |     102 |     103 |              1 | -only current line |
+---------+---------+---------+---------+---------+---------+----------------+--------------------+

1 个答案:

答案 0 :(得分:1)

List.Intersect并不是非常适合计数重复行,因为此函数将只返回比较列表的全部中常见的那些项,并且仅返回一次

以下所有三个选项的功能基本相同,只是方法略有不同。
我们添加了一个计算列,该列将采用当前记录,为具有相同值(Table.SelectRows / List.Select)的记录过滤整个数据集,并计算过滤后的结果(Table.RowCount / {{3 }}。
由于两个具有相同值的记录不会被视为相等,因此必须首先对两个要比较的记录进行转换,方法是在每个记录上调用List.Count或在整个数据集上调用Record.ToList

选项1

在比较期间将每个表格行转换为列表。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Dupes = Table.AddColumn(Source, "Dupes", (CurrentRecord) =>
        Table.RowCount(
            Table.SelectRows(Source, (CompRecord) =>
                Record.ToList(CurrentRecord) = Record.ToList(CompRecord)
            )
        )
    )
in
    Dupes

选项2

在比较之前将表转换为列表(记录)的列表(表)。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Dupes = Table.AddColumn(Source, "Dupes", (CurrentRecord) =>
        List.Count(
            List.Select(Table.ToRows(Source), (CompRecordAsList) =>
                Record.ToList(CurrentRecord) = CompRecordAsList
            )
        )
    )
in
    Dupes

选项3

在比较和使用变量之前,请将表转换为列表(记录)的列表(表),以避免重复调用Record.ToList
我不知道Record.ToList有多昂贵。对于大型数据集,这可以提高性能。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Dupes = Table.AddColumn(Source, "Dupes", (CurrentRecord) =>
        let
            CurrentRecordAsList = Record.ToList(CurrentRecord),
            ReturnValue = List.Count(
                List.Select(Table.ToRows(Source), (CompRecordAsList) =>
                    CurrentRecordAsList = CompRecordAsList
                )
            )
        in
            ReturnValue
    )
in
    Dupes

根据评论中的说明进行编辑

选项4

寻找独立于列的公共值。

由于您只想对n-m列中的n列值完全相等的行进行计数,因此我们确实可以使用Table.ToRows而不是直接相等比较。
以下内容基于选项3 ,但在所有三种情况下均相同。我们用对这两个列表的调用CurrentRecordAsList = CompRecordAsList代替List.Intersect(其中每个列表代表一个记录,即每个列表项代表其中一列的值),计算公共项的数量,并与n-m(在这种情况下为5)进行比较。

注意事项#1:不再匹配所有列匹配的项目,这意味着所得的数字现在仅表示 other 记录。不包括相等比较中计算的当前记录。
平等比较:1表示没有重复(仅发现自我)
Intersec比较:1表示已找到一个 other 记录

注意#2::这不会检查公共值是否位于比较记录的同一列中。只有两个记录中的某处出现值。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Dupes = Table.AddColumn(Source, "Dupes", (CurrentRecord) =>
        let
            CurrentRecordAsList = Record.ToList(CurrentRecord),
            ReturnValue = List.Count(
                List.Select(Table.ToRows(Source), (CompRecordAsList) =>
                    List.Count(List.Intersect({CompRecordAsList, CurrentRecordAsList})) = 5
                )
            )
        in
            ReturnValue
    )
in
    Dupes

选项5

如果您还需要检查公用值是否在同一列中,则List.Intersect不再有用。

下面发生的事情与以前相同。我们添加了一个计算列,该列获取当前记录,过滤完整的数据集,并对过滤的记录进行计数。只是过滤条件现在稍微复杂一点。
用于过滤数据集的自定义函数使用List.Intersect获取列名列表,通过使用Table.ColumnNames比较两个记录的对应列来过滤此列表(List.Select),对所得的公共列(Record.Field),并将其与阈值n-m(例如5)进行比较。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Dupes = Table.AddColumn(Source, "Dupes", (CurrentRecord) =>
        Table.RowCount(
            Table.SelectRows(Source, (CompRecord) =>
                List.Count(
                    List.Select(Table.ColumnNames(Source), (ColumnName) =>
                        Record.Field(CurrentRecord, ColumnName) = Record.Field(CompRecord, ColumnName)
                    )
                ) = 5
            )
        )
    )
in
    Dupes