盆暗の学習記録

データサイエンスを中心として,日々学んだことの備忘録としていく予定です。初心者であり独学なので内容には誤りが含まれる可能性が大いにあります。

pythonによるe-stat APIからのデータ取得

前回に引き続いて,公的データの取得に関してメモ。

Rだと便利なライブラリがあるが,Pythonだとやや面倒かも。

賃金構造基本統計調査 雇用形態別DBを例に説明していく

アプリケーションIDの用意

e-Statでユーザー登録し,アプリケーションIDを取得してコードに貼り付けておく

# 読み込み
app_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

APIアクセス用メソッドの定義

共通する処理なのでメソッドにしておく

import pandas as pd
import urllib
import json
# GETリクエストの送信からjson受け取り,dictへの変換までの流れを行うメソッド
def get_estat_data(api_method: str, params: dict, api_version="3.0", return_format="json") -> dict:
    url = f"https://api.e-stat.go.jp/rest/{api_version}/app/{return_format}/{api_method}?{urllib.parse.urlencode(params)}"
    req = urllib.request.Request(url)
    with urllib.request.urlopen(req) as res:
        response = res.read()
    return json.loads(response.decode())

統計情報の取得

普通に人力で探す場合

APIのgetStatsListを使う場合

  • APIで調べることもできる
    • メソッドのURLはgetStatsList
  • 全件取得する場合はパラメータにappIdのみを入れる

  • パラメータを設定することで,条件で絞り込んで取得できる

    • searchWordに値を入れればキーワードで検索することもできる
params = {
    "appId": app_id,
    "searchWord": "賃金構造基本統計調査 雇用形態別" # キーワードで検索
}
stats_list = get_estat_data(api_method="getStatsList", params=params)
stats = stats_list["GET_STATS_LIST"]["DATALIST_INF"]["TABLE_INF"]
stats_df = pd.io.json.json_normalize(stats)
stats_df[["@id","STAT_NAME.$","STATISTICS_NAME","TITLE","CYCLE","SURVEY_DATE"]].head()

@idの「0003082750」が目的のstatsDataId

f:id:nigimitama:20190810165015p:plain

メタ情報の取得:getMetaInfo

  • 一度に取得できるデータの上限は10万レコード
  • 縦持ちテーブルでデータがDLされるので,この上限にはすぐに達してしまう
    • リクエストパラメータで指定できるように,予め必要なデータ項目(変数,カラム)を調べておく必要がある
    • getMetaInfoで調べられる
  • getMetaInfostatsDataIdが必須パラメータなので,先程取得したIDを入れる

メタ情報の取得

stats_data_id = "0003082750"
params = {"appId": app_id, "statsDataId": stats_data_id}
meta_info = get_estat_data(api_method="getMetaInfo", params=params)

CLASS_INF:データに関する情報

class_info = meta_info["GET_META_INFO"]["METADATA_INF"]["CLASS_INF"]["CLASS_OBJ"]

# 中身を見やすいように整形
tab = pd.io.json.json_normalize(class_info[0], record_path="CLASS")
cat01 = pd.io.json.json_normalize(class_info[1], record_path="CLASS")
cat02 = pd.io.json.json_normalize(class_info[2], record_path="CLASS")
cat03 = pd.io.json.json_normalize(class_info[3], record_path="CLASS")
cat04 = pd.io.json.json_normalize(class_info[4], record_path="CLASS")
cat05 = pd.io.json.json_normalize(class_info[5], record_path="CLASS")
cat06 = pd.io.json.json_normalize(class_info[6], record_path="CLASS")
cat07 = pd.io.json.json_normalize(class_info[7], record_path="CLASS")
cat08 = pd.io.json.json_normalize(class_info[8], record_path="CLASS")

f:id:nigimitama:20190810165736p:plain

f:id:nigimitama:20190810170015p:plain

これらの中身を見て,必要なデータを取得するためのコードを把握しておく。

統計データの取得:getStatsData

params = {
    "appId": app_id,
    "statsDataId": stats_data_id,
    "cdTab": tab.loc[4, "@code"],
    "cdCat01": cat01.loc[0,"@code"],
    "cdCat02": cat02.loc[0,"@code"]
}
stats_data = get_estat_data(api_method="getStatsData", params=params)

DATA_INF:統計データ

# DATA_INF: 統計データ
data_info = stats_data["GET_STATS_DATA"]["STATISTICAL_DATA"]["DATA_INF"]

ここにはNOTEVALUEが入っている(data_info.keys()で確認できる)

f:id:nigimitama:20190810173732p:plain

NOTEは統計表上の欠損値の記号とその意味についての注釈文

# NOTE:欠損値の記号などについての注意書き
data_info["NOTE"]

f:id:nigimitama:20190810173812p:plain

VALUEは目的の統計データ

# VALUE: 統計データ
data_df = pd.io.json.json_normalize(data_info, record_path="VALUE")
data_df.head()

f:id:nigimitama:20190810174118p:plain

データは正規化されていて,例えば性別の「男性」が「01」というコードに変換されたような形で入っている。

CLASS_INFで取得したデータとJOINさせて整形していく必要がある(これが面倒…)

pythonによるRESAS APIからのデータ取得

今までRでしか取得したことがなく,Pythonでは初めてだったのでメモ

使い方の流れ

  1. 利用登録してAPIキーを取得
  2. RESAS-API - API概要を見て,取得するデータを決める
  3. 取得したいデータのURLにGETリクエストを送れば(アクセスすれば)JSON形式でデータを取得できる
    • urllibライブラリのurllib.request.Request()メソッドで取得できる
    • パラメータ(?cityCode=11362みたいなやつ)を付加する場合はurllib.parse.urlencode()を使う
  4. 取得したJSONデータを整形する
    • jsonライブラリのjson.loads()pythonの辞書型に変換
    • pandaspd.io.json.json_normalize()などで辞書型をDataFrame型に変換

コードの例

RESASデータ取得用の関数

import urllib
import pandas as pd
import json
api_key = {"X-API-KEY": "ここに取得したAPIキーを入力"}


def get_resas_data(params: dict, api_path: str, api_key: dict) -> dict:
    api_endpoint = "https://opendata.resas-portal.go.jp/"
    url = api_endpoint + api_path
    url = (url + "?" + urllib.parse.urlencode(params)) if (params != None) else url
    req = urllib.request.Request(url, headers = api_key)
    with urllib.request.urlopen(req) as res:
        response = res.read()
    resas_data_dict = json.loads(response.decode())
    return resas_data_dict

例:都道府県一覧の取得

# 都道府県一覧の取得
resas_data = get_resas_data(params=None, api_path="api/v1/prefectures", api_key=api_key)
prefectures = pd.io.json.json_normalize(resas_data['result'])

f:id:nigimitama:20190804205207p:plain

例:市区町村一覧の取得

cities = pd.DataFrame()
for i in range(1,48):
    resas_data = get_resas_data(params={"prefCode": i}, api_path="api/v1/cities", api_key=api_key)
    cities_i = pd.io.json.json_normalize(resas_data['result'])
    cities = pd.concat([cities, cities_i], axis=0)

f:id:nigimitama:20190804205142p:plain

例:出生数・死亡数/転入数・転出数の取得

都道府県や市区町村とは異なり,こういうデータは返ってくるJSONがネスト(入れ子)していて整形が面倒。

pd.io.json.json_normalize()やpandasの前処理関数(例えばpd.DataFrame.pivot())を駆使して整形していく。

例えば,次のように,リストと文字列が入っている辞書型データは,pd.io.json.json_normalize()できれいにデータフレームに変換できる

# 辞書の入ったリストと文字列を含む辞書型データ
data_dict = {'data': [{'value': 34780, 'year': 1995},
                        {'value': 36035, 'year': 2000},
                        {'value': 46769, 'year': 2005}],
                        'label': '総人口'}
# record_pathにリストのキーを指定,metaにそれ以外のキーを指定
pd.io.json.json_normalize(data_dict, record_path="data", meta=["label"])

f:id:nigimitama:20190804204500p:plain

データの取得

といった知識をもとに書いたコードがこれ

api_path = "api/v1/population/sum/estimate"
params={"prefCode": 13, "cityCode": 13101}
resas_data = get_resas_data(params=params, api_path=api_path, api_key=api_key)
data_list = resas_data["result"]["data"]
for i in range(len(data_list)):
    resas_df_i = pd.io.json.json_normalize(data_list[i], record_path="data", meta=["label"])
    resas_df_i = resas_df_i.pivot(index="year", columns="label", values="value").reset_index()
    resas_df = resas_df_i if i == 0 else pd.merge(resas_df, resas_df_i, on="year")

f:id:nigimitama:20190804204844p:plain

WSLのvimの背景ハイライトがおかしいのを直す方法

問題

WSLでvimを起動し,Ctrl + DCtrl + Uなどを押すとハイライトがバグってしまいます。

f:id:nigimitama:20190727222034p:plain

デフォルトのカラースキームだと目立たないバグですが,自分でデフォルト以外のカラースキームを設定していると色がめちゃくちゃになってしまうこともあります。

解決策

背景色・文字色を指定する

~/.vimrc

highlight Normal ctermfg=white ctermbg=black

のような値を追記するというもの。

これにより,背景色(ctermbg)と文字色(ctermfg)を任意の値に固定します。

:help cterm-colorsコマンドを使うとvimで設定できる色の名前一覧を見ることができるので,これを見ながら自分が使用しているカラースキームに合わせた色に設定するとよさそうです。

(非推奨)Background Color Eraseオプションを無効にする

~/.vimrc

set t_ut=""

を設定する方法。

こちらはカラースキームを気にしなくていい対処法ですが,バグったハイライトが一瞬でて正常に戻る感じなので,バグがチラつく感じ。

一応こちらも書いておきますが,前節の対処法のほうがいいです。

参考

ssh接続についてのメモ

※環境

Windows 10 1093
WSL Ubuntu 18.04

例えばEC2インスタンス作成時に受け取ったpemファイルや,ssh-keygenコマンドで生成した鍵を使う。

keygen1:雑な方法

コマンドを叩くだけ。

ssh-keygen

そうするとEnter file in which to save the key (/home/hogehoge/.ssh/id_rsa):と聞かれるが,SSH Keysの保存先を聞かれているだけなので,Enterを入力

続いてEnter passphrase (empty for no passphrase):と言われるが,なくても作れる(そして秘密鍵が盗まれないかぎり安全)のでEnterを入力する。

最低限のセキュリティをもった2048bit RSAの鍵はこれで作れる。

keygen2:丁寧に作る方法

ちょっとオプションを足してコマンドを叩き

# 4096bit RSA鍵
ssh-keygen -t rsa -b 4096
# 521bit ECDSA鍵(15360bit RSA鍵に相当するらしい)
ssh-keygen -t ecdsa -b 521

ちゃんとパスフレーズを設定する(秘密鍵が盗まれてもパスフレーズがわからないと使えないのでより安全)

というのがセキュリティ的には望ましいらしい。

参考

.ssh/configの書き方

.sshディレクト

ディレクトリがなければ作成し,

mkdir ~/.ssh
chmod 700 .ssh

sshディレクトリのパーミッションは700(管理者にのみ全権付与)にする。

参考:chmod コマンド - Qiita

configファイル

ファイルがなければ作成する

touch ~/.ssh/config
chmod 600 ~/.ssh/config

権限を管理者に限定しないと,以下のようなエラーが出る

Bad owner or permissions on /home/fuga/.ssh/config

configには次のような記法で書き込む。

Host hoge_server
    HostName hogehoge.com
    User fugafuga
    IdentityFile ~/.ssh/hoge.pem
    Port 22

参考:.ssh/configファイルでSSH接続を管理する - Qiita

接続

configに記載したHostの名前で指定する

ssh hoge_server

パーミッション関連のエラー

このとき,鍵ファイルのパーミッションが適切に設定されていない場合,次のようなエラーが出る

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                             
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @                             
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                             
Permissions 0666 for '/home/fugafuga/.ssh/hogehoge.pem' are too open.

Are you sure ? を省略する

また,初回接続時に

Are you sure you want to continue connecting (yes/no)?

と聞かれるが,VS Codeのremote developmentなどではこれが出ると邪魔くさいので

.ssh/configStrictHostKeyChecking noを追記すればこれを省略できる。

Host hogehoge
    ...
    StrictHostKeyChecking no

vimで編集中のプログラムを実行する

初めて知ったのでメモ

概要

:w ![当該言語の実行コマンド]

f:id:nigimitama:20190713232443g:plain

:![当該言語の実行コマンド] %

f:id:nigimitama:20190713232054g:plain

:!clear; [当該言語の実行コマンド] %

f:id:nigimitama:20190713235404g:plain

コンパイルする場合)

f:id:nigimitama:20190713233912g:plain

コンパイラ言語の場合は長いので何かエイリアスを.vimrcに入れたほうがいいですね

意味

vimコマンド

  • w:記述中のファイルを保存
  • !:shellコマンドを実行する
  • %vimで編集中のファイルのこと

bash/shellコマンド

  • clearbashの過去の履歴をクリアする(画面外に追いやる,Ctrl+Lと同等)
  • ;:複数行に渡るコマンドを1行で続けて書くときの記法
  • &&:この演算子の左側の処理が正常に終了した場合,右側に書かれた処理を行う演算子

参考

Google Apps Scriptの基本の使い方と企業での活用事例

Google Apps Script(以下GAS)というGoogleが提供している言語(とその開発環境,実行環境)があります。

GASは次のような特徴を持っています。

  1. Googleのサーバーで関数単位で実行してもらえる
  2. 「毎日朝8時に実行」「1時間毎に実行」といったタスクを設定できる
  3. 文法はほぼJavaScriptと一緒

無料だし,サーバーを用意しなくていので,定期的に行わせたいちょっとした処理があるときに便利です。

最近ちょくちょく使うので「どうやって使うのか」「どのように使われているのか」についてメモしておきます。

始め方

.gsファイルの新規作成

  • Google Driveでファイルを新規作成するときに選べます
  • 見当たらなければ「アプリを追加」から追加

f:id:nigimitama:20190711210350p:plain

編集画面

  • 実行する関数を選択して,黒い三角のボタンを押すとプログラムを実行することができます
  • 時計みたいなアイコンから「Google Apps Scriptダッシュボード」に移動できます
  • ダッシュボードでは「こういう条件が満たされたら関数を実行する」といったトリガーの作成・管理を行うことができます

f:id:nigimitama:20190711213332p:plain

書き方の例

だいたいjavascriptみたいな書き方してれば動きますが,GAS独自のクラスなんかもたくさんあります。

Hello World

  • jsならconsole.log()ですが,GASではLogger.log()を使って出力します
  • ログは ctrl+Enter で閲覧できます
function hello() {
  Logger.log('Hello World');
}

Spread Sheetの編集

Google Spreadsheetのデータを読み込んだり,書き込んだりできます。

function getDataFromSheet() {
  // シートを開く
  const SHEET_URL = "";
  const SHEET_NAME = "";
  var spreadSheet = SpreadsheetApp.openByUrl(SHEET_URL);
  var sheet = spreadSheet.getSheetByName(SHEET_NAME);
  
  // データ全取得
  var data = sheet.getDataRange().getValues();
  
  // 結果を表示
  Logger.log(data);
}
function addDataToSheet() {
  // シート指定
  const SHEET_URL = "";
  var spreadSheet = SpreadsheetApp.openByUrl(SHEET_URL);
  
  //  2番目のシートを選択
  var sheet = spreadSheet.getSheets()[1];

  // 任意の範囲に値を書き込み
  sheet.getRange(1, 1, 2, 2).setValues([["Orange", 130],
                                        ["Grape", 200]]);
  // 末尾に行を追加
  sheet.appendRow(["Apple", 130]);
}

Googleのサービスとの連携部分はとくに丁寧に作られていて,他にも,Goole Slidesに書き込んだり,Gmailから送信したりもできます。

企業によっては業務で使うデータをSpreadsheetで管理・共有していると思いますので,Spreadsheetからの入出力の自動化や,そこからの書類作成・プレゼン作成などの「次のアクション」を省力化できる点で非常に魅力的な技術だと思います。

使い方の例:企業での活用事例

どのように使われているのか,少し調べてみました。

スタートアップでのGAS活用事例 - Speaker Deck

  1. 日報管理
  2. タイムカード管理
  3. 記事集計表:記事を管理する別のシートからデータをもってきて集計
  4. シャッフルランチ(社内制度)の抽選を行うアプリ
  5. 予算管理表
  6. KGI・KPI管理表

といったものに使っていらっしゃるようです。なるほど…。

ダッシュボードのように「進捗をひと目でわかるようにしたい」というニーズで,かつ,「出力は表形式が適している」ようなデータを使って集計表・管理表を作っている感じでしょうか。

GAS(Google Apps Script)業務利用の事例

  • Google Formの利用申請フォームに入力された情報を,Formと結びついたSpreadsheetから取得し,メールで通知してくれるアプリ
  • GASはGoogle Formに紐づけている

社内でのやりとりがメールでなくSlack等のチャットツールである企業の場合は,メールでなくチャットツールに通知させてもいいでしょうね(例えばSlackならAPIを使って)。

Google Apps Script 活用ミートアップ #2

  1. 営業チームごとの管理シートを集計し,結果を別のシートに書き出す
  2. Gmailから新規営業候補になり得る情報をリスト化してsheetに書き出し,slackに通知
  3. 指定した単語を指定した色でハイライトするChrome拡張

gmailに来るメールから有用な情報を発掘しようとする使い方は非常にユニークですね。

このイベントの詳細:
好評につき、Google Apps Script 活用ミートアップ(GAS活)の第2回目を開催しました! - Gaiax Engineers' Blog

Slackのログをスプレッドシートと連携して技術メモの整理に使っている話 - Qiita

企業の事例と言うか,エンジニア個人の活用事例ですが,面白い使い方かと思います。

私もSlackをメモ代わりに使うことが多いのでいつか使うかも

おわりに

GAS公式ページには色々なサービスと連携させていろいろできることが書いてあります。

GASのファイル自体をWebAPIにしたり,HTMLを入れてWebアプリにしたりもできるみたいです(参考)。

GASでできることが多すぎて私も把握しきれていません…

私は今の所,SpreadsheetをSlackAPIやその他のAPIと組み合わせて使ったりするくらいです。

「ちょっとした業務効率化アプリをササッと作る」といった用途にはとっても適しているように思いますので,今後も機会を見つけてGASを学んでいこうと思います。

[Windows]コマンドラインで「自分のいつもの環境」を簡単に再現する

自分がWindowsで環境を用意するときに便利だなとおもったものをメモしておきます。

省力化のポイントは「極力コマンドラインで操作する」ということかなと思うようになりました。

そうすれば,「自分にとって必要なソフトウェアのリスト」をコマンド集としてメモしておけば,新しいPCを買ったときとかにそのコマンド集を実行すればいいので。

scoop

scoopとは

パッケージ管理ツールというやつで,いろんなアプリをコマンドラインpowershell)から簡単にインストール・アップデートできるようにするもの。

例えばgoogle chromeをインストールするときに,普通なら

  1. Edgeを開いて「Google Chrome」と検索する
  2. Chromeの公式サイトでダウンロードする
  3. ダウンロードしたファイルを実行してインストールする

という手順を踏むものだが,scoopなら

scoop install chrome

と入力するだけでダウンロードとインストールが自動で行われる。

こっちのほうが断然楽。

ちなみに,Windowsのパッケージ管理ツールにはChocolateyというものもある。でもこれを読んでscoopのほうが良さそうに思えたのでscoopにした。

(特に,Chocolateyはインストールのたびにユーザーアカウント制御が出てしまう,というのは致命的な気がするので,もし今のバージョンのchocolateyでも同様の仕様であるならばscoop一択な気がする)

install

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
iex (New-Object net.webclient).downloadstring('https://get.scoop.sh')

パッケージのインストールの例

scoop install git
scoop install python
scoop install r

Bucketの追加

bucketとは,ソフトウェアの公式サイトへのリンク集的なやつ。

bucketを追加すると,scoopでインストールできるソフトが増える

extras bucket

公式のbucket

など,いろんなソフトをダウンロードできるようになる

# Bucketの追加
scoop bucket add extras

extrasによってインストールできるようになるソフトウェアの例:

# Google Chrome: おなじみの大人気ブラウザ
scoop install chrome

# WinRAR: .zip, .rarなどの圧縮・解凍ソフト
scoop install winrar

# MPC-HC: 動画ビューア
scoop install mpc-hc

# irfanview: 複数画像の一括編集機能などがついた多機能の画像ビューア
scoop install irfanview

# ScreenToGif: 画面をGIFの動画としてキャプチャする
scoop install screentogif

# GIMP: Photoshopのような画像編集ソフト
scoop install gimp

# R Studio: R言語のエディタ
scoop install rstudio

# Open Hardware Monitor: CPUやGPUの使用率,温度などをモニターする
scoop install openhardwaremonitor

scoopでのダウンロードに向いていないソフト

次のようなソフトは手動でインストールする必要がありそう。

  • slack

    • extras bucketからダウンロード可能だが,インストールが失敗した
  • docker

    • デフォルトのbucketからダウンロード可能だが,うまく起動しなかった
  • steam
    • extras bucketからダウンロード可能だが,インストール後に保存先を移動したりとかの処理(必須ではないが推奨されているみたい)が面倒
  • QTTabBarエクスプローラをタブ化するソフト)

    • あるbucketからダウンロード可能だが,インストールがうまくいかなかった
  • Rictyなどのフォント

    • jpというbucketにあるが,ダウンロードまではうまくいくもののインストールがうまくいかない。

参考

WSL1

WSLとは

WSL(Windows Subsystem for Linux):Windows内でLinux OSのようなものを動かすやつ

WSLの機能の有効化

管理者権限でPowerShellを起動し,次を実行

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -Force

Linuxディストリビューションのダウンロード

ざっくり分けて,次の2つのインストール方法がある模様

  1. Microsoft Storeからダウンロード・インストールする
  2. PowerShellからダウンロードして,実行ファイルをクリックしてインストールする

例えばPowerShellからのUbuntu 18.04のダウンロードは次のように行う。

# ダウンロード
Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu-1804 -OutFile Ubuntu.appx -UseBasicParsing
# 実行
start Ubuntu.appx
# 削除
rm Ubuntu.appx

参考