将链接列表转换为十字路口网格的 Power Query

Power Query to Convert List of Links to Grid of Crossings

在 Excel 中,我有一个用标识符标记的配对项目的数据 table。本质上,命名链接。

工作表:链接

Tag Point-A Point-B
Route 1 Home Office
Route 2 Home Grocery 1
Happy Hour Office Bar
Sad Hour Office Dump
Headaches Bar Pharmacy
Sick Bar Dump
Route 3 Office Moms
Route 4 Office Park
Victory Park Bar
Discard Park Dump

我想将此数据转换为行和列中所有点的网格,并将标记放置在交叉点(很像带有城市距离网格的旧纸质道路地图)

工作表:网格

A \ B Bar Dump Grocery 1 Home Home Moms Office Office Park Pharmacy
Bar Sick Happy Hour Victory Headaches
Dump Sick Sad Hour Discard
Grocery 1 Route 2
Home Route 1
Home Route 2
Moms Route 3
Office Happy Hour Sad Hour Route 1 Route 3
Office Route 4
Park Victory Discard Route 4
Pharmacy Headaches

我写了下面的M转换代码,但是好像有点任性,过头了。我是用点的位编码来构造连接键的,所以咬过程大概会突破32个点。

是否有更短的一组 LET 对网格进行相同的转换?

有没有办法创建一个 Min(Point-A,Point-B)Max(Point-A,Point-B) 定界连接的密钥,从而不依赖 bitting

M 代码(从高级编辑器复制)

let
    LinksTable = Table.SelectRows(Excel.CurrentWorkbook(), each [Name] = "Links"),
    Links = Table.RemoveColumns(Table.ExpandTableColumn(LinksTable, "Content", {"Tag", "Point-A", "Point-B"}), "Name"),
    AllPoints = Table.Combine(
    { Table.SelectColumns(Table.RenameColumns(Links,{"Point-A", "Point"}), "Point"),
      Table.SelectColumns(Table.RenameColumns(Links,{"Point-B", "Point"}), "Point")
    }),
    ThePoints = Table.Sort(Table.Distinct(AllPoints),{"Point"}),
    PointsIndexed = Table.AddIndexColumn(ThePoints, "Index", 0, 1, Int64.Type),
    PointsBitted = Table.RemoveColumns(Table.AddColumn(PointsIndexed, "Bit", each Number.Power(2, [Index]), Int64.Type),"Index"),
    AllPairsBitted = Table.Join(
      Table.RenameColumns(PointsBitted, {{"Point", "Point-A"}, {"Bit", "Bit-A"}}), {},
      Table.RenameColumns(PointsBitted, {{"Point", "Point-B"}, {"Bit", "Bit-B"}}), {},
      JoinKind.FullOuter
    ),
    AllPairsKeyed = Table.RemoveColumns(
      Table.AddColumn(AllPairsBitted, "BitKeyPair", each Number.BitwiseOr([#"Bit-A"],[#"Bit-B"])),
      { "Bit-A", "Bit-B"}
    ),    
    #"Links-A-Bitted" = Table.Join(
    Links, "Point-A",
    Table.RenameColumns(PointsBitted,{{"Point", "Point-A"}, {"Bit", "Bit-A"}}), "Point-A"
  ),
    #"Links-AB-Bitted" = Table.Join(
    #"Links-A-Bitted", "Point-B",
    Table.RenameColumns(PointsBitted,{{"Point", "Point-B"}, {"Bit", "Bit-B"}}), "Point-B"
  ),
    LinksKeyed = Table.RemoveColumns(
      Table.AddColumn(#"Links-AB-Bitted", "BitKeyLink", each Number.BitwiseOr([#"Bit-A"],[#"Bit-B"])),
      { "Bit-A", "Bit-B"}
    ),
    AllPairsTagged = Table.Sort( Table.RemoveColumns(
    Table.Join(
      AllPairsKeyed, "BitKeyPair",
      Table.SelectColumns(LinksKeyed, {"BitKeyLink", "Tag"}), "BitKeyLink",
      JoinKind.LeftOuter
    ),
    {"BitKeyPair", "BitKeyLink"}
  ),
  {"Point-A", "Point-B"}
),
    Grid = Table.Pivot(AllPairsTagged, List.Distinct(AllPairsTagged[#"Point-B"]), "Point-B", "Tag", List.First)
in
    Grid

我认为您可以使用 PIVOT 来实现这一点。直接使用此功能将不起作用,因为您正在寻找列和行的对称性。

诀窍是强制对称,将 Point-B 中的值附加到 Point-A 的值中。

步骤

  1. 创建一个辅助 table 并以与原始 table 相反的方式对列重新排序,因此 TagPoint-BPoint-A
  2. 在辅助 table 上,按顺序将列重命名为 TagPoint-APoint-BAppend 通常按字面意思使用列名,因此如果不重命名,它会附加相同列的名称。
  3. PivotPoint-B 没有聚合数据。
  4. 使用 Point-A 作为参考对列重新排序,使列和行对称。

值得一提的是 Buffer 来源 table 是一个很好的做法,因为它在整个计算过程中被多次使用。

计算

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("Zc69CsMgEMDxVwnOLv14ghKoS2looEvIcJwXIkEMZxx8+6axiUInwd/99bpOvFxYqDoJKZSztB7PYTBIope7nbPd2SFxXMe/rGCeY6Vc4JxJcQPetAX9Z3Wwc0oJNOBI/hdI0YzAFjCm1uB0yBGldS7lgw9nfWHX0hrgabO3wcVx3K/yirXxCKwzpK/6Dw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Tag = _t, #"Point-A" = _t, #"Point-B" = _t]),
    BufferedSource = Table.Buffer(Source),
    SecondTable = Table.ReorderColumns(BufferedSource,{"Tag","Point-B","Point-A"}),
    SecondTableRenameCols = Table.RenameColumns(SecondTable,{{"Point-A","Point-B"},{"Point-B","Point-A"}}),
    AppendTables = Table.Combine({BufferedSource,SecondTableRenameCols}),
    PivotTables = Table.Pivot(AppendTables, List.Distinct(AppendTables[#"Point-B"]), "Point-B", "Tag"),
    ReorderCols = Table.ReorderColumns( PivotTables, PivotTables[#"Point-A"])

in ReorderCols


输出

Point-A Bar Dump Grocery 1 Home Moms Office Park Pharmacy
Bar Sick Happy Hour Victory Headaches
Dump Sick Sad Hour Discard
Grocery 1 Route 2
Home Route 2 Route 1
Moms Route 3
Office Happy Hour Sad Hour Route 1 Route 3 Route 4
Park Victory Discard Route 4
Pharmacy Headaches