[[20220812224147]] 『PowerQuery(powerpivot? dax?)ででワイルドカード』(りり) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『PowerQuery(powerpivot? dax?)ででワイルドカード使った値と一致させて、データを置換する方法が知りたいです』(りり)

もし分かりましたら、教えていただけますと非常に助かります。
データ件数がネックで、excelでは難しく、accessでは時間かかり、
時にはデータファイル破損も何度も経験しており、
もし可能ならPowerPivotで一気に処理できるのでは、と
一縷の望みを持って質問させていただきました。

【やりたいこと】
テーブルXのB列を埋めたい。
テーブルYのA列とテーブルXのA列を一致させて、
テーブルYのB列をテーブルXのB列に一気に流し込みたい。

【前提条件】
テーブルXのデータ件数が 数千万件 あります。
Accessでデータを分けて、数百万件ずつ実行していましたが、
相当な時間かかる上煩雑なため、他の方法を模索したい。

【PowerQueryを使用した方法を知りたいです】
PowerQueryではデータ成形が可能で、バックに2億のデータをもった上での
処理も可能なので、ここで一度に処理できたら助かります。
方法がありましたら、DAX? PowerPivot? 組み方を知りたいです。

■テーブルX

	A	       B	    
1   [置換前]      [置換後★解]
2  トヨタ愛知        トヨタ
3  株式会社トヨタ      トヨタ
4  トヨタ株式会社      トヨタ
5  トヨタ名古屋整備     トヨタ	

■テーブルY(置換内容)

	A	       B	     	
1  [置換内容]      [置換後]
2  *トヨタ        トヨタ
3  *トヨタ株式会社    トヨタ
4  トヨタ*        トヨタ

よろしくお願いいたします m(_ _)m

< 使用 Excel:Excel2016、使用 OS:Windows10 >


トヨタ を含むものは、トヨタ にするということでしょうか?

(マナ) 2022/08/13(土) 08:03


検索してみました。
↓ここなどが使えませんか。
https://community.powerbi.com/t5/Power-Query/Power-Query-Bulk-replace-value-if-it-contain-a-value-from-a-list/td-p/1916267

(マナ) 2022/08/13(土) 08:12


マナさん、早速ありがとうございます。
そうです、アスタリスクはワイルドカードを意味してます。
ここでは、例としてトヨタしかないですが、
さまざまなものが実際はあります。
こちらのサイトのコード、入れて試してみますね。
どうもありがとうございます!
パワークエリまわりは、日本語情報がまだあまり
出回ってないですね。
英語の情報ソース、ドンピシャでいただき、
どうもありがとうございます!
助かります!!!

(りり) 2022/08/13(土) 09:24


すっかり時間が経過してしまいましたが。

ひとつの語を含む場合のケースを教えていただきましたが。
実際は、アスタリスクが複数存在する語もありまして。
その場合の式が知りたいです。
サンプルが悪くて申し訳ありません。
以下のようなケースを想定しています。

	A	       B	    
1   [置換前]      [置換後★解]
2  トヨタ愛知        トヨタ
3  株式会社トヨタ      トヨタ
4  トヨタ株式会社      トヨタ
5  トヨタ名古屋整備     トヨタ	
6  ミニトヨタ青森     トヨタ青森
7  田中トヨタ株式会社青森 トヨタ青森

■テーブルY(置換内容)

	A	       B	     	
1  [置換内容]      [置換後]
2  *トヨタ        トヨタ
3  *トヨタ株式会社    トヨタ
4  トヨタ*        トヨタ
5  *トヨタ*青森*     トヨタ青森

A列同士を結合し、YテーブルのB列の内容をXテーブルのB列に流し込みたいです。
PowerPivotで使用できる式が知りたいです。
M言語かと思いますが、知識がまだ浅く、単純結合の related では
うまくいませんでした。

お知恵をお借りできたら、大変助かります。
よろしくお願いいたします。

(  りり) 2022/09/23(金) 22:51


 検索してみました
https://www.google.com/search?q=powerQuary+RegularExpression
(´・ω・`) 2022/09/24(土) 06:51

おはようございます。^^
VBAでしたら正規表現も使えて、テキストベースで抽出後なら
アクセスからでもエクセルからでもインポート出来るのでは。
ちなみに
一億件、csvに書き出しましたが約5分ちょいでした。^^;
的外れでしたら、無視して下さいませ。
でわでわ
m(__)m
(隠居Z) 2022/09/24(土) 08:10

↑忘れて下さい。。。A^^;
m(__)m
winでは読み込むソフトも無くて、Mysqlでも大きすぎて
phpmyadminからの簡単インポートでは出来なかったです。
ちなみに書き出したcsvファイルサイズは3.23ギガバイトでした
( ̄▽ ̄)
済みませんでした。私ではお手上げ状態です。m(__)m
(隠居Z) 2022/09/24(土) 09:14

 PowerQueryで正規表現というのは、かなりトリッキーな感じですね。
 JavaScriptのRegExpを援用するようです。
 こういう細工を求められるなら、いっそのこと隠居Zさん提唱の
 VBA対応が良いと思いました。

 ちなみに、
 トヨタ青森だけは残すというのは本当ですか?

 テーブルY(置換内容)を上から実行していったら、
 *トヨタ*青森*     トヨタ青森
 に行き着く前に、単なる「トヨタ」に変換されてしまいますよね。
 そう単純には行かないでしょう。

 (1)最初に、*トヨタ*青森* がある場合に、使用頻度の低い文字列(例:"$$$$$$"とか)に置換しておいて、
 (2)*トヨタ*等を「トヨタ」に置換して、
 (3)最後に"$$$$$$"を「トヨタ青森」に戻す
 といった工夫が必要でしょう。
 テーブルYにも一層の工夫が必要で、VBAのほうが小回りが利いてたぶん簡単だと思います。
 (まあ、私のPowerQueryレベルが低劣なだけかもしれませんが)
  
(γ) 2022/09/24(土) 09:17

 ちょっと浅知恵SQLで実験してみました。

    WITH
    Y AS (
                  SELECT '%トヨタ' AS A,         'トヨタ' AS B FROM DUAL
        UNION ALL SELECT '%トヨタ株式会社' AS A, 'トヨタ' AS B FROM DUAL
        UNION ALL SELECT 'トヨタ%' AS A,         'トヨタ' AS B FROM DUAL
        UNION ALL SELECT '%トヨタ%青森%' AS A,   'トヨタ青森' AS B FROM DUAL
    )
    ,X AS (
                  SELECT 'トヨタ愛知' AS A             FROM DUAL
        UNION ALL SELECT '株式会社トヨタ' AS A         FROM DUAL
        UNION ALL SELECT 'トヨタ株式会社' AS A         FROM DUAL
        UNION ALL SELECT 'トヨタ名古屋整備' AS A       FROM DUAL
        UNION ALL SELECT 'ミニトヨタ青森' AS A         FROM DUAL
        UNION ALL SELECT '田中トヨタ株式会社青森' AS A FROM DUAL
    )
    SELECT
        X.A
        ,CASE WHEN X.A LIKE Y.A THEN Y.A END AS YA
        ,CASE WHEN X.A LIKE Y.A THEN Y.B END AS YB
    FROM
        X CROSS JOIN Y 

 ↓実行結果

 __|__________A___________|_______B_______|____C_____
  1|A                     |YA             |YB        
  2|トヨタ愛知            |               |          
  3|株式会社トヨタ        |%トヨタ        |トヨタ    
  4|トヨタ株式会社        |               |          
  5|トヨタ名古屋整備      |               |          
  6|ミニトヨタ青森        |               |          
  7|田中トヨタ株式会社青森|               |          
  8|トヨタ愛知            |               |          
  9|株式会社トヨタ        |               |          
 10|トヨタ株式会社        |%トヨタ株式会社|トヨタ    
 11|トヨタ名古屋整備      |               |          
 12|ミニトヨタ青森        |               |          
 13|田中トヨタ株式会社青森|               |          
 14|トヨタ愛知            |トヨタ%        |トヨタ    
 15|株式会社トヨタ        |               |          
 16|トヨタ株式会社        |トヨタ%        |トヨタ     ← どちらに引っ掛かっても結果的には「トヨタ」だからいいかもだけど
 17|トヨタ名古屋整備      |トヨタ%        |トヨタ     ← データベース的には2件該当、つまり一意になってないから、
 18|ミニトヨタ青森        |               |              仮にUPDATE文を書くとしても何らかの対策は必要。
 19|田中トヨタ株式会社青森|               |          
 20|トヨタ愛知            |               |          
 21|株式会社トヨタ        |               |          
 22|トヨタ株式会社        |               |          
 23|トヨタ名古屋整備      |               |          
 24|ミニトヨタ青森        |%トヨタ%青森%  |トヨタ青森 ← ↑と同様ではあるが、それ以前に期待する結果が得られていない
 25|田中トヨタ株式会社青森|%トヨタ%青森%  |トヨタ青森 ←   (γさんからご指摘済みの件)

 さて、どーしたものだか...

 (面白そうなので、秘かに行く末見守っときます ^^; )

(白茶) 2022/09/24(土) 10:48


 見守っとくにしても、ちょっとさすがに↑は乱暴過ぎましたかね。^^;

    WITH
    Y AS (
                  SELECT '^.*トヨタ$' AS A,         'トヨタ' AS B     FROM DUAL
        UNION ALL SELECT '^.*トヨタ株式会社$' AS A, 'トヨタ' AS B     FROM DUAL
        UNION ALL SELECT '^トヨタ.*$' AS A,         'トヨタ' AS B     FROM DUAL
        UNION ALL SELECT '^.*トヨタ.*青森.*$' AS A, 'トヨタ青森' AS B FROM DUAL
    )
    ,X AS (
                  SELECT 1 AS SEQ, 'トヨタ愛知' AS A             FROM DUAL
        UNION ALL SELECT 2 AS SEQ, '株式会社トヨタ' AS A         FROM DUAL
        UNION ALL SELECT 3 AS SEQ, 'トヨタ株式会社' AS A         FROM DUAL
        UNION ALL SELECT 4 AS SEQ, 'トヨタ名古屋整備' AS A       FROM DUAL
        UNION ALL SELECT 5 AS SEQ, 'ミニトヨタ青森' AS A         FROM DUAL
        UNION ALL SELECT 6 AS SEQ, '田中トヨタ株式会社青森' AS A FROM DUAL
        UNION ALL SELECT 7 AS SEQ, 'トヨタ部品株式会社青森' AS A FROM DUAL -- ←サンプル追加(課題提起)
    )
    SELECT DISTINCT
        X.SEQ
        ,X.A
        ,Y.B
        ,CASE
        WHEN REGEXP_LIKE(X.A , '^.*トヨタ.*青森.*$') THEN 'トヨタ青森' -- ←優先順位アゲてみる
        WHEN REGEXP_LIKE(X.A , '^.*トヨタ$')         THEN 'トヨタ'
        WHEN REGEXP_LIKE(X.A , '^.*トヨタ株式会社$') THEN 'トヨタ'
        WHEN REGEXP_LIKE(X.A , '^トヨタ.*$')         THEN 'トヨタ'
        END AS B2
    FROM
        X LEFT JOIN Y ON REGEXP_LIKE(X.A , Y.A)
    ORDER BY
        X.SEQ

 ↓実行結果

 _|___A____|__________B___________|____C_____|____D_____
 1|SEQ     |A                     |B         |B2        
 2|       1|トヨタ愛知            |トヨタ    |トヨタ    
 3|       2|株式会社トヨタ        |トヨタ    |トヨタ    
 4|       3|トヨタ株式会社        |トヨタ    |トヨタ     ← この場合ならDISTINCTで重複削除できる
 5|       4|トヨタ名古屋整備      |トヨタ    |トヨタ    
 6|       5|ミニトヨタ青森        |トヨタ青森|トヨタ青森
 7|       6|田中トヨタ株式会社青森|トヨタ青森|トヨタ青森
 8|       7|トヨタ部品株式会社青森|トヨタ    |トヨタ青森 ←┐
 9|       7|トヨタ部品株式会社青森|トヨタ青森|トヨタ青森 ←┴ 表結合では2件該当。CASE式は優先順位次第(件数によっては大変だし)

 しかし「数千万件」かぁ... 大変スね ^^;

(白茶) 2022/09/24(土) 17:58


 紹介のありました記事を読んで、簡単なサンプルを作ることしかできませんでした。

 テーブルのサンプルです。(Name2が置換後の列です)
 ID      Name                    Name2
 1       株式会社トヨタ          トヨタ
 2       ミニトヨタ株式会社      トヨタ
 3       ミニトヨタ青森          トヨタ青森
 4       トヨタ株式会社青森      トヨタ青森
 5       株式会社青森            株式会社青森  どれもマッチしないデータ

 詳細エディターにはこんなコードを入れています。
 let
     tbl = Table.FromRecords({
         [ID = 1, Name = "株式会社トヨタ"],
         [ID = 2, Name = "ミニトヨタ株式会社"],
         [ID = 3, Name = "ミニトヨタ青森"],
         [ID = 4, Name = "トヨタ株式会社青森"],
         [ID = 5, Name = "株式会社青森"]
     }),

     // 文字列置換関数
     replacer = (char as text) as text => Web.Page(
         "<script>
             var str1 = '" & char & "'.replace(/.*トヨタ.*青森.*/,'トヨタ青森'); 
             if(str1 !='トヨタ青森') 
             str1 = '" & char & "'.replace(/.*トヨタ.*/,'トヨタ'); 
             document.write(str1) ;
         </script>")[Data]{0}[Children]{0}[Children]{1}[Text]{0},

     // Name列の各要素にreplacerを作用させ、新しい列Name2を作成する
     tbl2 = Table.AddColumn(tbl, "Name2",   each replacer([Name]))
 in 
     tbl2

 各行ごとにStringオブジェクトのreplaceメソッドを呼んでいるので、効率は悪いでしょうね。
 (というより、Web.Pageでテーブルを作る処理がネックになるかも)
 数千万件ですか、ちょっと私の手には負いかねます。  
 頑張って下さい。

 # いっそテキストファイルベースで、pythonなりrubyなりでテキスト処理したほうが手っ取り早いかも。
 # 秀丸は1億行まではいけるそうですね。
  
(γ) 2022/09/25(日) 09:40

質問者さま、すみません。
ちょっとだけすみません。

># 秀丸は1億行まではいけるそうですね。

 5000万行300列 8GB CSVではじかれたことがあるのです。
 秀丸で何か読み込むテクとかあれば教えていただけるとうれしいです。
(他の人の質問のところで、本当に申し訳ないのですが・・・)

(まっち) 2022/09/26(月) 17:08


 ご指摘ありがとうございます。
 https://caddiary.com/?p=2861
 の記事タイトルをそのまま伝聞の形でお伝えしたまでです。
 貴兄の経験が質問者さんのお役に立つことを願っております。
  
(γ) 2022/09/26(月) 17:51

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.