見出し画像

Tableau Webデータコネクタ その1

はじめに

 Tableauを使ってオープンデータを分析する際、オープンデータの取得元がREST APIに対応している場合はWebデータコネクタを用意することで簡易に連携することができます。Webデータコネクタは、HTML、Javascript、CSSを使って作成し、Webサーバにホスティングする必要があり、私のようなプログラミング初心者がどこまで実装できるか検証していきたいと思います。

今回作成したWebデータコネクタ

 今回は、内閣府地方創生推進室が運営しているRESAS地域経済分析システムから地方の「創業比率」(既存の事務所数に対して新規に開設された事務所数の割合)を取得するAPIからWebデータコネクタを作成しました。

Webデータコネクタのコード

 今回作成したコードは以下になります。いくつかのサイトですでに作成されていたものを参考に作成しました。

(function () {
   var myConnector = tableau.makeConnector();
   
   var resas_api_prefcode_url = "https://opendata.resas-portal.go.jp/api/v1/prefectures";
   var resas_api_citycode_url = "https://opendata.resas-portal.go.jp/api/v1/cities";
   var resas_api_url = "https://opendata.resas-portal.go.jp/api/v1/municipality/foundation/perYear";
   var prefectureArray = [];
   var cityArray = [];
   

   
   //スキーマ定義
   myConnector.getSchema = function (schemaCallback) {
       var cols = [
           { id : "prefCode", alias : "県コード", dataType : tableau.dataTypeEnum.string },
           { id : "prefName", alias : "県名", dataType : tableau.dataTypeEnum.string },
           { id : "cityCode", alias : "市区町村コード", dataType : tableau.dataTypeEnum.string },
           { id : "cityName", alias : "市区町村名", dataType : tableau.dataTypeEnum.string },
           { id : "year", alias : "年", dataType : tableau.dataTypeEnum.string },
           { id : "value", alias : "創業比率", dataType : tableau.dataTypeEnum.int}
       ];

       var tableInfo = {
           id : "Foundation",
           alias : "創業比率",
           columns : cols
       };

       schemaCallback([tableInfo]);
   };

   //スリープ処理関数
   function sleep(msec) {
       return new Promise(function(resolve) {
           setTimeout(function() {resolve()}, msec);
       })
   };

   //コネクタにデータを登録
   var deferredObj = $.Deferred();
   myConnector.getData = function(table, doneCallback) {
       var tableData = []; 
       var resas_api_key = JSON.parse(tableau.connectionData).api_key;
       
       //都道府県コード取得
       console.log('X-API-KEY:'+resas_api_key);
       var xhr = $.ajax({
           type: 'GET',
           url: resas_api_prefcode_url,
           dataType: 'json',
           scriptCharset: 'utf-8',
           headers: { 'X-API-KEY': resas_api_key },
           async: false
       }).done(function(resp) {
           resp.result.forEach(function(data) { prefectureArray.push(data); });
       }).fail(function() {
           tableau.abortWithError('An error has occured while trying to connect to prefectures api.');
       });   
       sleep(1000);

       //市区町村コード取得
       prefectureArray.forEach(function(data) { 
           var xhr = $.ajax({
                       type: 'GET',
                       url: resas_api_citycode_url + '?prefCode=' + data.prefCode,
                       dataType: 'json',
                       scriptCharset: 'utf-8',
                       headers: { 'X-API-KEY': resas_api_key },
                       async: false
           }).done(function(resp) {
               resp.result.forEach(function(data) { cityArray.push(data); });
           }).fail(function() {
               tableau.abortWithError('An error has occured while trying to connect to cities api.');
           });
           sleep(1000);
       });
       
       sleep(1000);


       deferredObj.resolve();
       //市区町村でループ
       deferredObj.promise().then(function() { 
           cityArray.forEach(function(data) { 
               var xhr = $.ajax({
                           type: 'GET',
                           url: resas_api_url + '?prefCode='
                               + data.prefCode + '&cityCode=' + data.cityCode,
                           dataType: 'json',
                           scriptCharset: 'utf-8',
                           headers: { 'X-API-KEY': resas_api_key },
                           async: false
               }).done(function(resp, textStatus) {
                   if (resp.result == null){ return;}
                   resp.result.data.forEach(function(data){
                       tableData.push({
                           "prefCode": resp.result.prefCode,
                           "prefName": resp.result.prefName,
                           "cityCode": resp.result.cityCode,
                           "cityName": resp.result.cityName,
                           "year": data.year,
                           "value": data.value
                       });    
                   })
               }).fail(function() {
                   tableau.abortWithError("An error has occured while trying to connect to foundation api.");
               });
               sleep(1000);
           });
       });
       table.appendRows(tableData);
       doneCallback();         
   };

   tableau.registerConnector(myConnector);
})();
   
$(document).ready(function () {
   $("#submitButton").click(function () {
       var api_key = document.getElementById('app_id_input').value;
       tableau.connectionData = JSON.stringify({ api_key: api_key });
       tableau.connectionName = "RESAS 創業比率";
       tableau.submit();
   });
});

実際のWebデータコネクタ

 作成したWebデータコネクタは以下で公開しています。
 ・Webデータコネクタ
 ・ソースコード(github)

はまった点

 市区町村コードリストをRESASの別のAPIで取得した後、ループする処理を入れていますが、すべての市区町村に創業比率データがあるわけではないので、取得できなかった場合に次のループに移る(いわゆるcontinue的な)処理を入れる必要がありました。

その他注意点

 RESASはリクエスト数に制限があります。1分間のリクエストは5回まで、1日のリクエスト数は10,000回までです。市区町村コードが約1,900あるため、データ取得の検証を5回やると6回目には「Too many requests...」というエラーで怒られます。1日10,000回は少ないので多くしてほしいと思うところです。

参考にさせていただいたサイト、記事

以下のサイトを参考にさせていただきました。貴重な記事を作成いただき、ありがとうございました。

TableauによるRESAS-API接続(課題解決メカニズムを創造するデータデザイナー)


いいなと思ったら応援しよう!