LoginSignup
2
2

More than 3 years have passed since last update.

バスの料金表をテーブルに変換する

Last updated at Posted at 2019-06-29

twitterでバスの料金表を読み取るExcel問題を見かけたので、Power Queryでの変換クエリを考えてみました。
無駄に長い感があり、完敗です。
他の回答例など、コメントいただけるとうれしいです。
※2019/6/30追記:クエリ例その2を入れました。

料金表の例

例によって、下記のコードを詳細エディタに貼ると、テーブルになります。

元の料金表
let
    Source = "vZK7DsIwDEX/xXMH5+mmK59BGdqmmQpMmRD/jpsCSnhULHSxfBRF58bx/gK78xSPJwENtNEI27fRkqy5H0hwld60kaR16XTgSkJCdb8moZGID1JM5km6IFOQLYigUYjXKgtzitOUSTibIyPbWGvtlmyQW7GwYmHF71amNWuOahmQ934eRG3gVyEWwvVnvghz1IvfBvY76/ibFPapBpX6kPoBtkiSo1mCOUm8J0Z1/EeOwsdt+WuIHO3bxjgUnEyPiHNK28E2KXKkFEqPfl5gFRCuhxs=",
    Custom1 = Binary.Decompress(Binary.FromText(Source),Compression.Deflate),
    Custom2 = Table.FromRecords(Json.Document(Custom1))
in
    Custom2

料金表の様子
image.png

変換するクエリ:その1

当初思いついた案です。

コード

let
    Source = 元の料金表,
    #"Filled Down" = Table.FillDown(Source,Table.ColumnNames(Source)),
    #"Reversed Rows" = Table.ReverseRows(#"Filled Down"),
    Custom1 = Table.ToColumns(#"Reversed Rows")& 
              {{"発駅"} & List.RemoveFirstN(List.Reverse(Record.ToList(#"Reversed Rows"{0})),1) },
    Custom2 = Table.FromColumns(Custom1),
    #"Promoted Headers" = Table.PromoteHeaders(Custom2, [PromoteAllScalars=true]),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Promoted Headers", {"発駅"}, "着駅", "料金"),
    合成前 = Table.SelectRows(#"Unpivoted Other Columns", each Value.Type([料金]) = type number),
    Custom3 = List.Transform(Table.ToRows(合成前),each {_{1},_{0},_{2}}),
    Custom4 = Table.FromRows(
                    List.Distinct(Table.ToRows(合成前)& Custom3),
                    type table[発駅=text,着駅=text,料金=Int64.Type]
              )
in
    Custom4

処理途中の画像

Reversed Rows

image.png

Custom1

image.png

Custom2

image.png

Unpivoted Other Columns

image.png

完成図

image.png

変換するクエリ:その2

考え直した案です。大分すっきりしました。

コード

let
    Source = 元の料金表,
    各行をリストにしてNull除去 = List.Transform(Table.ToRows(Source),each List.RemoveNulls(_)),
    駅リスト = List.Transform( 各行をリストにしてNull除去,each _{0} ),
    片側データ =List.Combine(
                     List.Transform( 各行をリストにしてNull除去,each 
                        [発=_{0},
                         着= List.RemoveFirstN(駅リスト,List.PositionOf(駅リスト,発)+1),
                         料金=List.RemoveFirstN(_,1),
                         料金一覧 =List.Zip({List.Repeat({発},List.Count(着)),着,料金})
                        ][料金一覧]
                    )
               ),
    逆データ =List.Transform(片側データ,each {_{1},_{0},_{2}}),
    テーブル化 =Table.FromRows( 片側データ& 逆データ,type table[発=text,着=text,料金=Int64.Type] )
in
    テーブル化

解説

ポイントは、「片側データ」の箇所で、「着」のリストを得ることです。一例を挙げます。
image.png

駅リストの後ろに挿入する
    x=各行をリストにしてNull除去{2}{0},      //・・・"川内"が返って来ます
    y=List.PositionOf(駅リスト,x),     //・・・2が返ります。(0始まりで数える)
    z=List.RemoveFirstN(駅リスト,y+1),    //・・・川内より後の駅リストが返ります。

テストコードを本コードに挿入して試すと、川内より後の4駅が取れていることが分かります。
image.png

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2