1
votes

Transposer partiellement la table

J'ai un fichier CSV contenant des informations sur certains lots de production. Lorsqu'il est chargé dans l'éditeur Excels PowerQuery, le tableau ressemble à ceci:

Batch    Date         RawMaterials    Amounts
123      01.01.2020   Fe              70
                      Cr              19
                      Ni              11
234      01.02.2020   Fe              72
                      Cr              17
                      Ni              11

Pour rendre ce tableau plus lisible, je cherche un moyen de le transposer juste partiellement pour le transformer en un format comme ceci:

Batch    Date         RawMaterial1    RawMaterial2    RawMaterial3    Amount1    Amount2    Amount3
123      01.01.2020   Fe              Cr              Ni              70         19         11
234      01.02.2020   Fe              Cr              Ni              72         17          9

Y a-t-il un moyen de réaliser cela avec PowerQueryM seul?


0 commentaires

3 Réponses :


2
votes

Cela semble fonctionner

Dépivote toutes les colonnes sauf les deux premières

Dupliquer la colonne de données

Changer le type de colonne en nombre pour forcer une erreur sur les colonnes non numériques

Transformez toutes les erreurs en quelque chose de reconnaissable, comme 999999999999

Filtrez en fonction de cela en deux tables, et ajoutez un index à chaque table

Fusionnez les deux tables ensemble

Ajouter une nouvelle colonne, en utilisant l'index pour voir si Batch est identique à la ligne précédente pour éliminer les doublons

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Date", "Batch"}, "Attribute", "Value"),
#"Duplicated Column" = Table.DuplicateColumn(#"Unpivoted Other Columns", "Value", "Value - Copy"),
#"Changed Type" = Table.TransformColumnTypes(#"Duplicated Column",{{"Value - Copy", type number}}),
#"Replaced Errors" = Table.ReplaceErrorValues(#"Changed Type", {{"Value - Copy", 999999999999999}}),
#"Filtered Rows" = Table.SelectRows(#"Replaced Errors", each ([#"Value - Copy"] = 999999999999999)),
#"Filtered Rows2" = Table.SelectRows(#"Replaced Errors", each ([#"Value - Copy"] <> 999999999999999)),
Index1 = Table.AddIndexColumn(#"Filtered Rows", "Index", 0, 1),
Index2 = Table.AddIndexColumn(#"Filtered Rows2", "Index", 0, 1),
#"Merged Queries" = Table.NestedJoin(Index2,{"Index"},Index1,{"Index"},"Index3",JoinKind.LeftOuter),
#"Expanded Index3" = Table.ExpandTableColumn(#"Merged Queries", "Index3", {"Value"}, {"Value.1"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded Index3",{"Attribute", "Value - Copy"}),
#"Added Custom" = Table.AddColumn(#"Removed Columns", "Batch.1", each if [Index] = 0 then [Batch] else if #"Removed Columns"{[Index]-1}[Batch] = [Batch] then null else [Batch]),
#"Added Custom2" = Table.AddColumn(#"Added Custom", "Date.1", each if [Index] = 0 then [Date] else if #"Removed Columns"{[Index]-1}[Batch] = [Batch] then null else [Date]),
#"Removed Columns1" = Table.RemoveColumns(#"Added Custom2",{"Batch", "Date", "Index"}),
#"Reordered Columns" = Table.ReorderColumns(#"Removed Columns1",{"Batch.1", "Date.1", "Value.1", "Value"})
in  #"Reordered Columns"


1 commentaires

Super boulot! Cela marche. En prime, j'aimerais savoir si vous pouvez changer les textes en double en une chaîne vide (s'ils sont dans des lignes consécutives, voir la question initiale). Cela améliorerait à nouveau la lisibilité du tableau.



1
votes

Tout d'abord, un grand merci à @horseyride. J'ai beaucoup appris de votre code suggéré. Malheureusement, lorsque j'ai essayé d'ajouter la colonne de date à la zone de pivotement, j'ai trouvé une petite faille dans le code. Mais grâce aux leçons que j'en ai tirées, j'ai pu produire une version légèrement plus générique qui suit essentiellement le même algorithme.

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}}),
    #"Unpivot Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Batch"}, "Attribut", "Wert"),
    Filter1 = Table.SelectRows(#"Unpivot Columns", each ([Attribut] <> "Amount1" and [Attribut] <> "Amount2" and [Attribut] <> "Amount3")),
    ModFilter1 = Table.AddColumn(Filter1, "Benutzerdefiniert", each if [Attribut] = "Date" then [Attribut] else [Wert], type text),
    Filter2 = Table.SelectRows(#"Unpivot Columns", each ([Attribut] <> "RawMaterial1" and [Attribut] <> "RawMaterial2" and [Attribut] <> "RawMaterial3")),
    #"IndexFilter1" = Table.AddIndexColumn(ModFilter1, "Index", 0, 1),
    #"IndexFilter2" = Table.AddIndexColumn(Filter2, "Index", 0, 1),
    #"Join Filtered Indexes" = Table.NestedJoin(IndexFilter1,{"Index"},IndexFilter2,{"Index"},"IndexFilter2",JoinKind.LeftOuter),
    #"Expand Joined Column" = Table.ExpandTableColumn(#"Join Filtered Indexes", "IndexFilter2", {"Wert"}, {"IndexFilter2.Wert"}),
    #"Remove Columns" = Table.RemoveColumns(#"Expand Joined Column",{"Index", "Attribut", "Wert"}),
    #"Rename Columns" = Table.RenameColumns(#"Remove Columns",{{"Benutzerdefiniert", "Attribut"}, {"IndexFilter2.Wert", "Wert"}})
in
    #"Rename Columns"

Je garde la réponse de horseyrides cochée comme la bonne réponse pendant qu'il résout mon question initiale telle qu'elle était.


0 commentaires

2
votes

Cela peut être fait un peu plus simplement:

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],,
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Batch", Int64.Type}, {"Date", type date}, {"RawMaterial1", type text}, {"RawMaterial2", type text}, {"RawMaterial3", type text}, {"Amount1", Int64.Type}, {"Amount2", Int64.Type}, {"Amount3", Int64.Type}}),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Batch", "Date"}, "Attribute", "Value"),
    #"Split Column by Character Transition" = Table.SplitColumn(#"Unpivoted Other Columns", "Attribute", Splitter.SplitTextByCharacterTransition((c) => not List.Contains({"0".."9"}, c), {"0".."9"}), {"Type", "Index"}),
    #"Pivoted Column" = Table.Pivot(#"Split Column by Character Transition", List.Distinct(#"Split Column by Character Transition"[Type]), "Type", "Value")
in
    #"Pivoted Column"
  1. Décompressez toutes les colonnes sauf les deux premières.
  2. Divisez la colonne Attribut en une partie de texte et une partie d'index (dans l'interface graphique: Transform> Split Column> By Non-Digit to Digit).
  3. Pivotez en arrière sur la colonne de la partie de texte (choisissez Ne pas agréger dans les options avancées de la colonne de pivot).


0 commentaires