ラベル JSON の投稿を表示しています。 すべての投稿を表示
ラベル JSON の投稿を表示しています。 すべての投稿を表示

2023/03/12

[Power Query] for ループのような処理を Power Query で行う方法

connpass や Doorkeeper の REST API を利用してIT勉強会のデータを取得して、Excel であれば JSON データを表形式のテーブルに展開し Pivot テーブルに取りこんで分析する、Power BI であれば、ファクトテーブルとして取りこんでレポート、ダッシュボード作成に利用する、などを過去のブログでも紹介しています。

その中で既に使っているやり方なんですが、意外にこの方法で悩んでいる方もいらっしゃるので、まとめて説明してみます。おおまかな手順は以下です。

1) APIを使ったデータ取得をパラメータを受け取って処理する関数にする
2) 渡したいパラメータ(for の 1 から n に相当)の要素をもったテーブルを作る
3) 要素をパラメータとして関数に渡し、結果をとる
4) エラーが発生している行を削除する
5) 関数の結果からピボットテーブルを利用する

ここから connpass の場合を例にとって説明します。Doorkeeper でも考え方は同じです。

1) APIを使ったデータ取得をパラメータを受け取って処理する関数にする

connpass の API の説明ページは以下で、そこでデータ取得のためのサンプルや、各種パラメータの説明があります。

connpass API リファレンス

https://connpass.com/api/v1/event/?keyword=JAWS のように keyward= に検索したいワードを入れることでレスポンスを JSON 形式で受け取ることができます。connpass の場合はレスポンスのデータ件数の初期値が10なので10件しか出力されないのですが、このcount パラメータは最大100に設定でき、かつ、初期値1の開始位置パラメータの start を設定することで 1-100、その次は 101-200、さらにその次は 201-300 と出力を受け取ることができます。URLは以下のようなものを生成できればいいわけです。

1-100件目を取得
https://connpass.com/api/v1/event/?keyword=JAWS&count=100&start=1
101-200件目を取得
https://connpass.com/api/v1/event/?keyword=JAWS&count=100&start=101
201-300件目を取得
https://connpass.com/api/v1/event/?keyword=JAWS&count=100&start=202

キーワードやcountは固定、start パラメータを上述のように変更してリクエストしすべての結果を貰って処理します。

以下は上述の 1-100件目を取得のURLを使って、connpass から JSON データを取得し、ワークシートにテーブルとして展開する手順です。VBAなどのコードを書かずにダイアログ設定だけで JSON をワークシートのテーブルとして展開できることがわかると思います。

[データ]タブの[データの取得と変換](これが Power Query) グループの [Webから] を選択して、URL の入力ボックスに上述のURLをコピーする。

Power Queryエディタが立ち上がって、API リクエストの結果、受け取ったオブジェクトがアイコンで表示されるので、ここで右クリックメニューから [JSON] を選ぶ。

レスポンス情報の「まとめ」が表示される。ここでわかるのは 1番目から開始して、100件を返信として受け取って、可能な返信の件数は 1,135件ある、ということです。JSONで受け取った100件分は、events の List にはいっているので、[List] をクリックします。

Listが展開されて [Record] となりますが、この Record をクリックしてしまうと1件分だけが展開されます。これを全件展開してたいので、リボンの左はしにある [テーブルへの変換] をクリックします。

[テーブルへの変換] 確認のダイアログが表示されるので、そのまま [OK] 

リスト形式のものが「テーブル形式」に変換されます。これによる赤丸の「展開」ボタンで、すべての行にある「レコード」が展開されます。

ここでレコードに含まれる内容が確認できます。このまま OK で構いませんが、[元の列名をプレフィックスとして使用します] のチェックをオフにして、column1 というプレフィックスを消した方が冗長な列名にならずにすみます。

100件分がテーブルとして展開されます。


リボンの [閉じて読み込む] をクリックすると、Powery Query を閉じて、ワークシート上に JSON のレスポンス結果をテーブルに変換したデータが作成されます。

これが基本形です。
この URL の start に受け渡す部分をパラメータ化して変更できる「カスタム関数」を作成します。

いくつかのやり方があるようです。ここでは以下のように「詳細エディター」で Powery Query の M言語を直接いぢります。

Powery Query エディターが閉じられている状態なら、Excel のリボンの [データ] タブの [クエリと接続] グループの [クエリと接続] をクリックし、クエリと接続 ペインを表示して、先ほど作成したクエリをダブルクリックして Power Query エディターを起動します。


[ホーム]タブの [クエリ]グループの [詳細エディタ-] をクリックします。

p1という文字列型のパラメータを宣言する以下の一部を let の前に入れます。URLの一部になるのでデータの属性は text (文字列) とします。

(p1 as text) =>

そして、URLの部分の start= の直後をダブルコーテーションで閉じて、&p1 を追加します。

ソース = Json.Document(Web.Contents("https://connpass.com/api/v1/event/?keyword=JAWS&count=100&start="&p1)),

[完了]ボタンで詳細エディターを終了します。

これでこのクエリはパラメーター入力が必要なクエリ関数になりました。
名前もわかりやすいものに変えておきましょう。右側の[クエリの設定]ペインの名前プロパティで変更可能です。

2) 渡したいパラメータ(for の 1 から n に相当)の要素をもったテーブルを作る

この作成した関数を使って、1,101、201、301、、、、とパラメータを入力して、すべてのデータをひとつのテーブルすると Excel 上では分析するデータソースとして使いやすいです。ワークシートに展開すると 100万行の制限がありますが、Pivotテーブルで利用するデータソースとして使う場合は、必ずしもデータをワークシートに接続する必要はなく、接続情報として保存することで Pivot テーブルのソースとして使えます。

さて、APIでリクエストをして何件あるかはそのとき時でかわります。ただ、上記で API を投げたとき、少なくとも現時点では 1,135 件あることは分かっているので、1,101,201,,,で、1401 とか、1901 まであればカバーできそうなのはわかっています。

そこで 1, 101, 201, 301... 1901 のパラメータリストを作り、そこのデータをパラメータとして関数に渡して、それぞれ100件分のデータを取りこむ、という手順を Power Query を使って踏んでいます。

まず、[データ]タブの[データの取得と変換]グループにある[データの取得]から、空のクリエを選択します。

19個のパラメータを作成するので、入力ボックスに ={1..19} と入力します。すると、1から19までの数字がはいったリストが作成されます。

リボンのテーブルへ変換をして、リストフィールドの数値を使って 1, 101, 201 を作る数式を使った追加の列を作ります。数式は n*100-99 を使ってみます。
テーブル変換した後で、[列の追加]タブの[カスタム列]を選択します。新しい列名はパラメータ変数名の p1 にして、使用できる列 Column1 をダブルクリックすると カスタム列の式に代入されます。そこに *100-99 を追記して [OK] をクリックします。


パラメータはテキストを渡すので、p1列名の横の [ABC123] ボタンを押して、属性をテキストに変換します。

3) 要素をパラメータとして関数に渡し、結果をとる
4) エラーが発生している行を削除する

ここからがカスタム関数を作った醍醐味です。[列の追加]タブの[カスタム関数の呼び出し]をクリックして、ダイアログを開きます。列名はそのままで、関数クエリのドロップダウンでは作成したカスタム関数が表示されるので、それを選びます。
関数を選ぶと、その関数のパラメータに何をいれるかを指定できるドロップダウンリストがでます。列名として指定した p1 をパラメータとして渡す設定をします。

すると関数名の列が新しく追加されます。

11行以降がデータが無いためErrorになるので、この行を削除します。追加列を選択した状態で、[ホーム]タブの[行の削除]から[エラーの削除]を選択します。

削除が終わったら、列名の左にある展開ボタンをクリックして、100件分のデータの展開をします。列名が長くなるので、[元の列名をプレフィックスとして使用します]のチェックを外し、[OK]をクリックします。(以降のサンプルの図は Column1 を外していない図になります。すみません)

各列の属性を適切なものにします。特に集計をしたい列は[10進数]とする、日付の列は [日付/時刻/タイムゾーン]を選んでから、[日付]を選び、[列タイプの変更]ダイアログで [新規手順の追加] を選択して、Excel が理解できる形式に変更してください。


最後は不要な列を削除します。(必要な列だけ選んで他の列を削除するという操作)

[閉じて読み込む]をクリックすると、Power Queryエディタを閉じて、結果をワークシートに展開します。1136行(=データは1,135)で、最初に確認したAPIの返答の result_available の数と一致していることがわかります。

5) 関数の結果からピボットテーブルを利用する 

ここまでくれば、あとは Pivotテーブルで集計できます。
すでにテーブル形式になっているので、[挿入]-[ピボットテーブル]で、この手順通りであれば [クエリ1]というテーブルが指定されている状態でピボットテーブルを作成します。
connpassの場合だと、started_at が開催日、accepted が申し込み人数で、Power Queryで日付データを Excel がわかる形式に変換しているので、以下のような Pivotテーブルが十数秒でできあがります。titleをカウントして何回の勉強会・イベントが開催されているかを集計しています。

この集計方法の最強にして最大の長所は「更新」できることです。一度、このピボットテーブルを作成してしまえば、[データ]タブの[すべて更新]をクリックすることで、再度 connpass に対して REST API を投げて、最新のデータを取得します。その間、Excel 下部のエリアに以下のような「バックグラウンド クエリを実行しています」メッセージが表示されます。

このメッセージが消えたら、ピボットテーブル上で右クリックメニューを表示して、そこから [更新] を選ぶことで、ピボットテーブルも最新になります。

注意すべき点

正確な集計にするためには keyword で取得した後のデータに「ゴミ」が混じっていないかのチェックを入念にしています。実際、この方法で取得したデータのテーブルはファクトテーブルであって、ある意味履歴のようなものです。対象とすべきデータなのかどうかのチェックはスタースキーマであればディメンジョンテーブル(マスターテーブル)と付き合わせるので、ピボットテーブル分析にいく手前で別のステップを踏んで、分析用のデータソーステーブルを作成します。[中止] などの言葉がタイトルにあれば省く、などの例外処理も気がついたら入れていくので、クエリは一度作ったら終わりではなく、常にデータの信頼性を担保するためのチェックをします。このケースの場合は、厳格な命名規則が適用されているわけではないので、毎週、毎月のように新規に追加されたデータから、クエリが正しいかを確認する作業をしています。

一方で、ゴミの有無だけではなく、データの取りこぼしが発生することも確認しています。理由ははっきりとわかっていませんが、一度取りこぼしたデータは次回の更新時にとってくることはないため、一次的なものというより keyword クエリにかからない connpass 側のデータの持ち方かと思います。この場合は強制的に event_id を指定すると詳細を取りこむことができるので、対象となるURL/event_idで強制取り込みリストを作り、そこを参照させて個別にデータを取りこむようにする工夫をしています。

過去の投稿と被っているところも多々ありますが、何かしらの参考になれば幸いです。

2017/06/15

[Excel] Excel で JSON データを読み込む

この前の投稿でご紹介したように、Power Query が「データの取得と変換」となって Excel の標準機能となり、様々なデータの取り扱いが可能になりました。(2017年6月現在、Office 365 サブスクリプションの 最新の Excel が機能拡張の対象となります)

データの取得と変換である Power Query は、アドイン単体としての機能追加、さらに Power BI Desktop の登場によって、Power BI Desktop の ETL 機能 (Extract, Transform, Load)として拡張が行われてきました。Power Query は、Excel そして Power BI Desktop のデータの取り込み、変換・加工、ロードを受けもつ ETL 機能として今も進化し続けています。

JSON 形式のデータをプログラミングなしで取り込む

この進化し続ける「データの取得と変換」機能で、すぐにでも使ってほしいのが CSV データの取り込み機能ですが、人によっては JSON 形式データの取り込みのほうを重宝するかもしれません。

というのも、JSON 形式のデータ取り込みは、以前からも Power Query を使ってできていたのですが、現在は空のクエリから詳細エディターを開いて Power Query 関数を手で記述することなく、クエリ エディターのクリック操作のみで取り込みが可能になったからです。

また、JSON形式のデータを表形式に変換してワークシート上に読み込むためには、VBAを使う方法がこれまで多く紹介されていましたが、VBAでプログラムすることなく、JSON形式のデータをワークシートに展開することができるようになりました。

Web から JSON でデータを取り込む

実際のところ、JSON形式のデータによるテキスト ファイルをフォルダーから読み込むよりも、Web 上での検索条件設定の結果で、JSON形式のデータが表示されることが多いと思います。

サンプルとして、IT勉強会の告知・募集でお世話になることが多い connpass さんの API を使ってみたいと思います。

https://connpass.com/


connpass さんは、イベントサーチ API を提供していて、検索クエリの条件に応じた一覧を JSON 形式のデータとして取得することができます。

connpass API リファレンス

Web API や REST API でデータ提供サービスをしています、という場合、上記のような API リファレンスのページが必ずありますので、探してみてください。

たとえば "BI" というキーワードでイベントを検索するための URL は以下のようになります。

https://connpass.com/api/v1/event/?keyword=bi

この URL で、以下のような JSON 形式のデータによるレスポンスがブラウザに表示されます。


このデータを、Excel のワークシートに展開できるように2次元の表形式に「変換」して、私たちが読めるようにデータを加工することが、データの取得と変換のクエリ エディターだけでできます。上述のように VBA などでプログラミングをすること無しに可能です。

シンプルなデータの取り込み手順

JSON データの取り込みには2つの方法があります。ファイルから取り込む方法と、Web から取り込む方法です。ファイルから取り込む方法を使っても URL を指定することで Web からの取り込みが可能ですが、今回は「Web から」を使ってみます。


「Web から」のデータ取得は、これまでの Web クエリよりも高機能になっています。HTML ページの table だけではなく、今回のように JSON にも対応しているのです。

connpass の Web API 利用はサインインする必要がありません。以下のダイアログで "PowerBI" キーワードを含むイベントを検索する URL を入力し、OKをクリックします。(上記 JSON サンプルのキーワード "bi" の検索結果の数が多かったので、キーワードを PowerBI に変更しています。注意してください。)


接続が完了するとクエリ エディター ウィンドウが立ち上がり、以下の画面が表示されます。


注意点は、ここでファイルのアイコンの [connpass.com] をダブルクリックしてはいけません。アイコン上でマウスオーバーすると「開くにはダブルクリックします」というツールチップが表示されますが、ダブルクリックすると、現時点ではテキストファイルとして処理されてしまいます。リボンの [変換] タブの [形式を指定して開く] から [JSON] を選んでください



Json 形式で開くと以下のデータが表示されます。


results_returned、events、results_start、results_available の意味は、上述の API リファレンスに解説がありますので、詳細については後で参照してほしいのですが、情報から「指定した(PowerBI)キーワードの検索結果の総数は 19 件で、このファイル(データ)に含まれるのは 10 件、検索開始位置は 1 件目からですよ」という意味です。

あらかじめだいたいの件数がわかっている、もしくは取得する件数に上限を付けることができるのであれば、取得件数を 20 件に指定して全件を一気に取得することができます。PowerBI のサンプルは件数が少ないので、以下の検索条件にしてみます。

条件を変更(URLの変更)のため、クエリの設定の [適用したステップ] の [ソース] の横にある歯車マークをクリックします。


ダイアログの URL を変更します。取り込む件数の上限を 20 とするパラメーターの &count=20 を追記した URL です。


[OK] を押すと、results_returned が 19 に更新されます。


今回は例をシンプルにするために、検索結果で全件を取り込むパラメータを追加しました。また、匿名アクセスで利用が可能なので、認証に関する設定はありません。これらへの設定・対応はもちろん可能です。あらためて別の機会にご紹介したいと思います。

今、この状態は、検索したいキーワードを設定した URL をサーバーに送り、その結果を JSON 形式のデータとして Web 経由で 19 件取得しています。
この表示されているリストの events の List のリンクに、JSON 形式で 19件の検索結果の格納されています。
List のリンクをクリックすると、以下のように List リンク内のリストが 19件のデータとして展開されます。


Record のリンクをクリックすると、クリックした1件分だけの内容を確認することができますが、今回はすべての Record(勉強会)の詳細を一気に展開したいので、ここでリボンにある [テーブルへの変換] をクリックして、19件のレコードを含むリストを、テーブル(表)形式に変換します。すでに1件1レコードとして認識されているので、テーブルへの変換のダイアログのオプションはそのままで、[OK] ボタンをクリックします。


リストだったデータがテーブル形式になりました。


ここで Record リンクをクリックすると1件分のみの展開をしますが、テーブル形式に変換したことによる「列名」の Column1 の横にある [展開] ボタンを押すと、Record に含まれるデータをテーブル形式1件分のデータのみなした場合の列名の一覧が表示されます。ここで取り出す列を絞り込むこともできます。今回はすべての列を選択し、かつ、列名が長くなるので、[元の列名をプレフィックスとして使用します] のチェックをはずして、[OK] ボタンをクリックします。


JSON形式の元データを、21列19行のテーブル形式のデータに変換することができました。クエリ エディターの操作のみで1行もコードを書かずにここまでできました。


テーブル形式になったデータを Excel 向けに加工する

今回は Excel の「データの取得と変換」を使って connpass から検索結果を JSON 形式のデータで取得しました。その後、ここまでの処理・操作で、データはテーブル形式になりました。それぞれの列名がどのような意味なのか、connpass の API リファレンスのレスポンス フィールドで確認することが可能です。

ここで、必要な列や行のみを残す、といった加工が可能です。ここからの処理は、JSON だから特別、というものはなく、普通のテーブル形式のデータのフィルター オプションを操作する感覚でできるのは、クエリ エディターを使ったことがあれば理解できるでしょう。まだ慣れていない方は Power Query によるデータの加工や絞り込みについて、もう少しだけ情報収集するといいでしょう。

この connpass のデータや、特にサーバーからデータを取得した際に、Excel ユーザーが一瞬「おや?」と思うのは、日付データの扱いです。この日付データのトピックだけで結構長いお話になってしまうので、ここで詳細は割愛しますが、1つだけ意識してほしいのは、サーバーの日付形式のデータは、そのまま Excel で扱うことができない場合がある、ということです。


上記はデータ変換をせずにテーブル形式に変換したJSONデータをワークシートに読み込み、列名 started_at の1行目のセルの書式を表示したものです。2017-05-20T13:00:00+09:00 は勉強会・イベントの開始日のデータですが、Excel は単なる文字列として認識し、日付として扱っていません。
多くの場合、Excel は日付「らしい」文字列のセルへの入力があると、日付データの「シリアル値」に変換し、表示形式によって人間が日付と認識できるデータに見た目上変換します。残念ながら、2017-05-20T13:00:00+09:00 という ISO-8061 形式の文字列は Excel によって日付データと認識されなかった、となります。このままではシリアル値として扱っていないため、日付関連の関数の利用や演算ができません。

そのため、クエリ エディターで Excel が日付として認識できるように加工します。
データをワークシートに読み込む前の、クエリ エディター上で、対象となる日付のデータの started_at の列データを変換します。
started_at の列名をクリックし列を選択した状態で [変換] タブの [データ型の検出] を使ってもいいですし、この日付データ型は [日付/時刻/タイムゾーン] と呼ばれるものなので、列名横のデータ型のボタンを押して、明示的に選択することで変換可能です。[ABC 123] のアイコンが地球儀と時計のアイコンに変わります。


この変換ステップを行うことで、[日付/時刻] に変換できるようになります。[日付/時刻/タイムゾーン] に一度変換しないで、いきなり [日付/時刻] を選択すると Error になるので注意してください。データ型ボタンで [日付/時刻] を選ぶと、列タイプの変更 ダイアログが表示されるので、[新規手順の追加] を選んでください。[現在のものを置換] はタイムゾーン付きのデータに変換したステップを置き換えてしまうのでエラーになります。


このように日付データを変換して Excel のワークシートに読み込むことで、シリアル値として扱うことができます。

日本語データも特に問題なく扱うことができています。イベント(勉強会)の概要データの description は HTMLタグを含むテキストデータとして取り込まれています。ここからまた何らかの判断をしたい場合は、クエリ エディターの詳細エディター上で M 言語を使ってやってもいいですし、ワークシートに取り込んだ後で、関数や VBA を使ってもいいでしょう。


実際は考慮すべき点がいっぱい

今回は JSON 形式のデータでも、取得と変換のクエリ エディターを使うことで、プログラミングすること無しに Excel ワークシートに取り込むことができることを紹介するのが目的でした。しかし、それ以外のところで考慮すべきことが出てくるのが実際でしょう。

たとえば、取得する件数。サービスによっては上限が決まっていて、それ以上のデータの取得は、今回のような件数の指定のほかに、ページ数指定や、オフセット指定を使うことが推奨されます。
Power Query / 取得と変換のクエリ エディターで、詳細エディターを使ってこれらへの対応が可能です。ページ数やオフセットの「繰り返し」の処理は、URLを組み立てる一連のステップを「関数化」して、ページ数やオフセットを引数として渡す、という方法を使います。

この件数の上限への対応は結構「頭の体操」的なアイディアが必要になります。場合によっては CData さんの ODBC ドライバーを使うと幸せになれることがあります。
サイボウズの kintone の API も1回のリクエストあたりのデータ取得件数の上限がありますが、CData さんのドライバーを使うことで、その上限を気にせずにデータの取得が可能になります。

CData ODBC ドライバー一覧
https://www.cdata.com/jp/download/?f=odbc

Power Query/Excel 取得と変換/Power BI Desktop も標準機能としてさまざまなデータソースに対応していますが、CDataさんのような専業メーカーさんの ODBC ドライバーを試してみると、意外な発見や、解決策を見つけることができるかもしれません。

また、匿名アクセスではなく、ユーザー名+パスワード、アプリケーション登録による Web キーの利用など、サービスによって認証の方法はさまざまです。
connpass と同じくらい IT 勉強会の告知・募集・管理ツールで人気がある Doorkeeper の場合は、検索の URL の送信と一緒に Header データに認証情報を入れる必要があります。connpass は「Web から」の「基本」を使いましたが、Doorkeeper は「詳細設定」を使って、Header に認証情報をセットして、検索リクエストを送信する必要があります。Doorkeeper の API の解説には、Power BI Desktop や Excel クエリ エディターの具体的な設定方法や手順はないので、苦労するポイントでしょう。

登録して、Public API Access Token を取得
HTTP要求ヘッダーに Bearer を使ってトークンを追加
正直いうと、Doorkeeper API で Authorization Bearer に行きつくまで結構な時間がかかりました。

長くなりましたが、Excel のデータの取得と変換という新しい外部データ取り込みの仕組みを使うことで様々なデータソースへ接続し、様々なデータ形式のデータを扱うことができます。まだまだ進化中ですが、その方向はなるべくコーディングさせない方向で、JSON形式のデータであっても、コーディングなしでテーブル形式に展開して、ワークシートに取り込むことが可能です。

食わず嫌いせずに、この新しい機能をぜひ使ってみてください。

[追記] 最後まで読んでいただいてありがとうございます。取得と変換の機能の一つの「ピボットの解除」もJSON処理同様これまでVBAでなければできないと言われていた処理です。こちらもおすすめ機能なので是非使ってみてください。
https://road2cloudoffice.blogspot.jp/2018/03/blog-post.html

[追記] REST APIで取れないデータをWebページスクレイピングでとる方法を追加しました。
https://road2cloudoffice.blogspot.com/2020/05/excel-web.html
Powered by Blogger.

自己紹介

自分の写真
1989年新卒で日本IBMに入社しダウンサイジング担当としてホストコンピュータと繋げるオフコン、UNIX、PCサーバーのプロジェクトを担当。1997年 MSKK(現日本マイクロソフト)入社、NT4出荷に伴い企業向けサポート部門のビジネスマネージャーとして Excel 使いとなり、2002年 にMSMVPなどをサポートするユーザーコミュ二ティ部門を設立、部門をリード。2006年にMSKK退職後、企業向けのITトレーニング会社・団体に携わり、2014年頃よりPowerBI勉強会主催メンバーの一人として参画、そのコミュニティ活動で MSMVP for Data Platform PowerBI 2017受賞。https://mvp.microsoft.com/ja-jp/PublicProfile/5002635 同年にMVP Awardを返上し、アマゾン ウェブ サービス ジャパンに入社、コミュニティプログラム担当として現在に至る。