どこにでもいる30代SEの学習ブログ

主にプログラミング関連の学習内容。読んだ本の感想や株式投資についても書いてます。

pythonによる政府統計e-StatのAPI機能の使い方

f:id:predora005:20210107001006p:plain
*1

政府統計の総合窓口(e-Stat)」の統計データは、APIで取得可能です。ユーザ登録(無料)を行えば、誰でもAPIを利用できます。

Pythonを使って、API経由で人口動態のデータを取得し、matplotlibでグラフ表示しました。

f:id:predora005:20210131100819p:plain

[1] ユーザ登録

利用ガイドにしたがって、ユーザ登録します。メールアドレスを入力し仮登録します。

f:id:predora005:20210127185110p:plain

仮登録後メールに記載されているURLにアクセスし、本登録を行います。

利用する機能で「API機能」「地図で見る統計」をチェックします。チェックを外す理由は特に無いでしょう。

f:id:predora005:20210127185232p:plain

パスワードを入力するか、ソーシャルアカウント連携を行えば本登録完了です。

f:id:predora005:20210127185259p:plain

[2] アプリケーションIDの取得

ユーザ登録が終わったら、マイページからアプリケーションIDを取得します。

f:id:predora005:20210128212911p:plain

f:id:predora005:20210128212934p:plain

名称、URL、概要を入力します。以下は公式の引用です。

アプリケーションID取得時に入力する名称、URL、概要は後から変更しても構いません。また、URLについては、公開サイトで利用しない場合は、ローカルアドレス(「http://test.localhost/」等)を入力してください。

URLは公開サイトで利用しないので、ガイド通りのURLとしました。名称と概要は適当です。

f:id:predora005:20210128213035p:plain

[発行]ボタンを押すと、appId欄にアプリケーションIDが表示されます。

f:id:predora005:20210128213050p:plain

[3] 取得できるデータと統計表IDを確認する

e-Statの全てのデータがAPIで取得できるわけではありません。それでも数多くのデータが取得可能です。

また、APIで特定のデータにアクセスするには「統計表ID」が必要です。統計表IDは各データでユニークなIDです。ブラウザで取得したいデータの統計表IDを確認します。

[3-1] ブラウザで確認する方がAPIより楽

API機能でも確認できるのですが、結論としてはブラウザ「データベース | 統計データを探す | 政府統計の総合窓口」から確認する方が早いです。

データの数が1万を軽く超える数あるので、APIで取得しても見るのが大変です。

[3-2] ブラウザで統計表IDを確認する

ブラウザからデータベース | 統計データを探す | 政府統計の総合窓口にアクセスします。今回は分野から「人口・世帯」を選択し、最新の「人口動態調査」を探していきました。

f:id:predora005:20210130150401p:plain

f:id:predora005:20210130150407p:plain f:id:predora005:20210130150413p:plain f:id:predora005:20210130150417p:plain

最下層まで辿っていくと、[DB]と[API]が表示されます。[API]を押したら目的は達せられるのですが、いったん[DB]を選択してデータの中身を確認します。

f:id:predora005:20210130150422p:plain

データの中身が確認できたので、[API]を選択します。

f:id:predora005:20210130150428p:plain

API機能でアクセスするためのURLが表示されます。statsDataIdの後ろの数字が「統計表ID」です。appId(アプリケーションID)は空欄になっています。APIを使用する際は取得した自身のIDをセットします。

f:id:predora005:20210130150435p:plain

また、ファイル形式はXML,JSON,CSVのいずれかが選択できます。ファイル形式を変更すると、URLも自動的に変更してくれます。

appId=の後ろに取得したアプリケーションIDをコピーし、ブラウザでアクセスします。すると、データがXML形式で表示されました。

f:id:predora005:20210130150438p:plain

[4] メタ情報を取得する

「統計表ID」を用いてメタ情報を取得します。メタ情報は公式のAPI仕様によると次の通りです。

指定した統計表IDに対応するメタ情報(表章事項、分類事項、地域事項等)を取得します。

先程の人口動態調査ですと、行(年度:2018年, 2017年...)と列(出生率, 死亡数...)が取得できます。

[4-1] ブラウザで取得

まずは、ブラウザで確認します。下記URLをブラウザに入力します。

https://api.e-stat.go.jp/rest/3.0/app/getMetaInfo?appId={アプリケーションID}&statsDataId=0003411561&explanationGetFlg=N

f:id:predora005:20210130212013p:plain f:id:predora005:20210130212018p:plain

[4-2] Pythonで取得

Pythonで取得する際は、JSON形式で取得します。ブラウザではXML形式で取得しましたが、PythonではJSON形式の方が扱いやすいからです。

import requests

app_id = {アプリケーションID}
stats_data_id = 0003411561 # 年次別にみた人口動態総覧

# メタ情報取得のURL
url = 'https://api.e-stat.go.jp/rest/3.0/app/json/getMetaInfo?'
url += 'appId={0:s}&'.format(app_id) 
url += 'statsDataId={0:s}&'.format(stats_data_id)
url += 'explanationGetFlg=N&'   # 解説情報有無:無し

# メタ情報取得
json = requests.get(url).json()
print(json)
# {'GET_META_INFO': {'RESULT': {'STATUS': 0, 'ERROR_MSG': '正常に終了しました。', 'DATE': '2021-01-30T21:26:13.043+09:00'}, 
# 'PARAMETER': {'LANG': 'J', 'STATS_DATA_ID': '0003411561', 'EXPLANATION_GET_FLG': 'N', 'DATA_FORMAT': 'J'}, 
# 'METADATA_INF': {'TABLE_INF': ...(省略)...
# 'CLASS_INF': {'CLASS_OBJ': [{'@id': 'cat01', '@name': '人口動態総覧', 
# 'CLASS': [{'@code': '00110', '@name': '出生数', '@level': '1', '@unit': '人'}, ...(省略)...

取得したJSONから、行と列の情報を抽出します。

# メタ情報から各表のCLASS(行や列)を抽出
class_objs = json['GET_META_INFO']['METADATA_INF']['CLASS_INF']['CLASS_OBJ']
print(class_objs)
# [ {'@id': 'cat01', '@name': '人口動態総覧', 
#   'CLASS': [{'@code': '00110', '@name': '出生数', '@level': '1', '@unit': '人'}, ...(省略)...
#   {'@id': 'time', '@name': '時間軸(年次)', 
#   'CLASS': [{'@code': '2018000000', '@name': '2018年', '@level': '1'}, ...(省略)...

[5] 統計データの取得

APIの統計データ取得を用いて、データの中身(値)を取得します。

[5-1] ブラウザで確認

まずはブラウザで、どのようなデータ構造になっているのか確認します。

https://api.e-stat.go.jp/rest/3.0/app/getMetaInfo?appId={アプリケーションID}&explanationGetFlg=N

f:id:predora005:20210130224945p:plain

VALUEタグの中に値が格納されており、属性に何のデータかが示されています。属性はメタ情報と対応しています。「cat01」は「人口動態総覧」のカテゴリを示しており、「00110」は人口動態総覧のうち「出生数」であることを示しています。

[5-2] Pythonで確認

メタ情報の際と同様にJSON形式で取得します。

app_id = {アプリケーションID}
stats_data_id = 0003411561 # 年次別にみた人口動態総覧

# 統計データ取得のURL
url = 'https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData?'
url += 'appId={0:s}&'.format(app_id) 
url += 'statsDataId={0:s}&'.format(stats_data_id)
url += 'metaGetFlg=N&'          # メタ情報有無
url += 'explanationGetFlg=N&'   # 解説情報有無
url += 'annotationGetFlg=N&'    # 注釈情報有無

# 統計データ取得
json = requests.get(url).json()

# 統計データからデータ部取得
values = json['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE']

# jsonからDataFrameを作成
df = pd.DataFrame(values)
print(df)
#      @cat01       @time @unit        $
# 0     00110  2018000000     人   918400
# 1     00110  2017000000     人   946146
# 2     00110  2016000000     人   977242
# 3     00110  2015000000     人  1005721
# 4     00110  2014000000     人  1003609
# ...     ...         ...   ...      ...
# 3154  00430  1903000000  人口千対     1.44
# 3155  00430  1902000000  人口千対     1.43
# 3156  00430  1901000000  人口千対     1.43
# 3157  00430  1900000000  人口千対     1.46
# 3158  00430  1899000000  人口千対     1.53
# 
# [3159 rows x 4 columns]

JSON形式で取得したデータは、後で扱いやすいようにDataFrameに変換しました。

[5-3] IDやCODEを意味のわかる内容に置き換える

これは必須ではありませんが、データの可読性のためにやりました。

DataFrameの列名'@cat01', '@time'を一目見ただけだと意味が理解づらいですし、値も'00110'や'2018000000'となっており分かりづらいです。メタ情報を用いて、意味の分かる内容に置き換えます。

# 統計データのカテゴリ要素をID(数字の羅列)から、意味がわかる名称に変更する
for class_obj in meta_info:

    # メタ情報の「@id」の先頭に'@'を付与'した文字列が、
    # 統計データの列名と対応している
    column_name = '@' + class_obj['@id']
    
    # 統計データの列名を「@code」から「@name」に置換するディクショナリを作成
    id_to_name_dict = {}
    for obj in class_obj['CLASS']:
        id_to_name_dict[obj['@code']] = obj['@name']
    
    # ディクショナリを用いて、指定した列の要素を置換 
    df[column_name] = df[column_name].replace(id_to_name_dict)

# 統計データの列名を変換するためのディクショナリを作成
col_replace_dict = {'@unit': '単位', '$': '値'}
for class_obj in meta_info:
    org_col = '@' + class_obj['@id']
    new_col = class_obj['@name']
    col_replace_dict[org_col] = new_col

# ディクショナリに従って、列名を置換する
new_columns = []
for col in stats_data:
    if col in col_replace_dict:
        new_columns.append(col_replace_dict[col])
    else:
        new_columns.append(col)
        
df.columns = new_columns
print(df)
#      人口動態総覧 時間軸(年次)    単位        値
# 0       出生数   2018年     人   918400
# 1       出生数   2017年     人   946146
# 2       出生数   2016年     人   977242
# 3       出生数   2015年     人  1005721
# 4       出生数   2014年     人  1003609
# ...     ...     ...   ...      ...
# 3154    離婚率   1903年  人口千対     1.44
# 3155    離婚率   1902年  人口千対     1.43
# 3156    離婚率   1901年  人口千対     1.43
# 3157    離婚率   1900年  人口千対     1.46
# 3158    離婚率   1899年  人口千対     1.53
# 
# [3159 rows x 4 columns]

[6] matplotlibでグラフ表示

APIで取得した「年次別にみた人口動態総覧」のデータを、matplotlibでグラフ表示します。

[6-1] 数値に変換する

年が文字列になっているので、整数値に変換します。変換値は「年度」という新しい列に格納します。

# 時間軸(年次)を整数に変換
df['年度'] = df['時間軸(年次)'].map(lambda year: int(year.replace('年','')))

次は「値」列について、有効値以外をNaNに変換します。例えば、戦前には調査していなかったデータなどは"…"といった値が格納されています。NaNに変換後、列のデータタイプをfloat64に変換します。

import numpy as np

# 有効値以外をNaNに置換する
df['値'] = df['値'].replace(['***', '-', '.', '…'], np.nan)
df['値'] = df['値'].astype(np.float64)

[6-2] 出生率と死亡率を表示

出生率と死亡率をDataFrameから取り出し、折れ線グラフで表示します。

import matplotlib.pyplot as plt

# 出生率と死亡率を取得する
birth_rate = df[df['人口動態総覧'] == '出生率']
mortality_rate = df[df['人口動態総覧'] == '死亡率']

# 図と座標軸を取得
fig = plt.figure()
ax = fig.add_subplot(1,1,1)

# 折れ線グラフをセット
ax.plot(birth_rate['年度'], birth_rate['値'], label='出生率(人口千対)')
ax.plot(mortality_rate['年度'], mortality_rate['値'], label='死亡率(人口千対)')

# Y軸の範囲設定
ymax = max([ birth_rate['値'].max(), mortality_rate['値'].max() ])
ax.set_ylim([0, ymax])

# 凡例表示
ax.legend()

# 折れ線グラフを表示
fig.show()

2005年ごろを境に死亡率が出生率を上回り、人口が減少していることが分かります。

f:id:predora005:20210131100755p:plain

[6-3] 自然増減率を第二軸に追加

第二軸に自然増減率を第二軸に追加します。自然増減率が0以下になると、人口が減少することを意味します。

# 自然増減率を取得する
natutal_id_rate = df[df['人口動態総覧'] == '自然増減率']

# 自然増減率を第二軸にプロット
ax2 = ax.twinx()
ax2.plot(natutal_id_rate['年度'], natutal_id_rate['値'], 'C2', ls=':', label='自然増減率(人口千対)')
ax2.set_ylabel('自然増減率(人口千対)')
ax2.grid(axis='y', color='gray', ls=':')

出生率と死亡率が交わるタイミングと、自然増減率が0になるタイミングが一致しています。

f:id:predora005:20210131100819p:plain

終わりに

そこまで大きな苦労はなく、APIで統計データを取得できました。今後、他のデータと組み合わせたり、色々と有効活用できそうです。

[付録1] APIで統計表情報取得

個人的には、APIではなくブラウザで確認する方をオススメします。

[付1-1] ブラウザで試しに確認

ブラウザで次のURLを直接入力して確認します。

API機能のうち「統計表情報取得」を使用して確認します。

https://api.e-stat.go.jp/rest/3.0/app/getStatsList?appId={アプリケーションID}&limit=2

  • limit=2では、取得するデータを2データまでに限定します。

上記URLにアクセスすると、次の結果が得られます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GET_STATS_LIST xsi:noNamespaceSchemaLocation="https://api.e-stat.go.jp/rest/3.0/schema/GetStatsList.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <RESULT>
        <STATUS>0</STATUS>
        <ERROR_MSG>正常に終了しました。</ERROR_MSG>
        <DATE>2021-01-27T22:44:59.685+09:00</DATE>
    </RESULT>
    <PARAMETER>
        <LANG>J</LANG>
        <DATA_FORMAT>X</DATA_FORMAT>
        <LIMIT>1</LIMIT>
    </PARAMETER>
    <DATALIST_INF>
        <NUMBER>183998</NUMBER>
        <RESULT_INF>
            <FROM_NUMBER>1</FROM_NUMBER>
            <TO_NUMBER>1</TO_NUMBER>
            <NEXT_KEY>2</NEXT_KEY>
        </RESULT_INF>
        <TABLE_INF id="0003288322">
            <STAT_NAME code="00020111">民間企業の勤務条件制度等調査</STAT_NAME>
            <GOV_ORG code="00020">人事院</GOV_ORG>
            <STATISTICS_NAME>民間企業の勤務条件制度等調査(民間企業退職給付調査) 統計表 1 定年制と定年退職者の継続雇用の状況</STATISTICS_NAME>
            <TITLE no="1">(推計値) 定年制の状況</TITLE>
            <CYCLE>年次</CYCLE>
            <SURVEY_DATE>201601-201612</SURVEY_DATE>
            <OPEN_DATE>2019-03-20</OPEN_DATE>
            <SMALL_AREA>0</SMALL_AREA>
            <COLLECT_AREA>該当なし</COLLECT_AREA>
            <MAIN_CATEGORY code="03">労働・賃金</MAIN_CATEGORY>
            <SUB_CATEGORY code="02">賃金・労働条件</SUB_CATEGORY>
            <OVERALL_TOTAL_NUMBER>25</OVERALL_TOTAL_NUMBER>
            <UPDATED_DATE>2019-03-30</UPDATED_DATE>
            <STATISTICS_NAME_SPEC>
                <TABULATION_CATEGORY>民間企業の勤務条件制度等調査(民間企業退職給付調査)</TABULATION_CATEGORY>
                <TABULATION_SUB_CATEGORY1>統計表</TABULATION_SUB_CATEGORY1>
                <TABULATION_SUB_CATEGORY2>1 定年制と定年退職者の継続雇用の状況</TABULATION_SUB_CATEGORY2>
            </STATISTICS_NAME_SPEC>
            <DESCRIPTION/>
            <TITLE_SPEC>
                <TABLE_CATEGORY>(推計値)</TABLE_CATEGORY>
                <TABLE_NAME>定年制の状況</TABLE_NAME>
                <TABLE_EXPLANATION>1 事務・技術関係職種の従業員がいる企業41,314社について集計した。2 「定年年齢」内の数値は定年制がある企業を100とした場合の割合を示す。</TABLE_EXPLANATION>
            </TITLE_SPEC>
        </TABLE_INF>
        <TABLE_INF id="0003288323">
            ...(省略)...
        </TABLE_INF>
    </DATALIST_INF>
</GET_STATS_LIST>

[付1-2] Pythonで取得

Pythonで取得する際は、json形式で取得します。

# coding: utf-8

import sys
import requests

# エントリーポイント
if __name__ == '__main__':
    
    # コマンドライン引数からアプリケーションID取得
    if len(sys.argv) < 2:
        print('Usage:')
        print('  python3 {0:s} [appId]'.format(sys.argv[0]))
        sys.exit(1)
    app_id = sys.argv[1]
    
    # 統計表情報取得のURL
    url = 'https://api.e-stat.go.jp/rest/3.0/app/json/getStatsList?'
    url += 'appId={0:s}&'.format(app_id)
    url += 'limit=2'

    # 統計表情報取得
    json = requests.get(url).json()
    print(json)
# {'GET_STATS_LIST': {'RESULT': 
# {'STATUS': 0, 'ERROR_MSG': '正常に終了しました。', 'DATE': '2021-01-27T22:52:49.687+09:00'}, 
# 'PARAMETER': {'LANG': 'J', 'DATA_FORMAT': 'J', 'LIMIT': 1}, 
# 'DATALIST_INF': {'NUMBER': 183998, 'RESULT_INF': ...(以下略)...

アプリケーションIDをソースに直打ちしたくないので、コマンドライン引数で指定しています。

[付1-3] pandasのDataFrame形式に変換

json形式のままだと見づらいので、pandasのDataFrame形式に変換します。いったんディクショナリのリストにした後、DataFrameに変換します。

import pandas as pd

# 統計表情報から各表のデータ部取得
datalist = json['GET_STATS_LIST']['DATALIST_INF']['TABLE_INF']

# ディクショナリ形式にし、pandasのDataFrameに変換
dict_list = []
for data in datalist:
    dict = {}

    # 統計表ID
    dict['id'] = data['@id']
    
    # 政府統計コードと統計名
    dict['stat_id'] = data['STAT_NAME']['@code']
    dict['stat_name'] = data['STAT_NAME']['$']
    
    #タイトル
    if '$' in data['TITLE']:
        dict['title'] = data['TITLE']['$']
    else:
        dict['title'] = data['TITLE']
    
    # 担当機関
    dict['gov_code'] = data['GOV_ORG']['@code']
    dict['gov_name'] = data['GOV_ORG']['$']
    
    # ディクショナリをリストに追加
    dict_list.append(dict)

df = pd.DataFrame(dict_list)
print(df)
#    id          stat_id   stat_name                 title                           gov_code  gov_name
# 0  0003288322  00020111  民間企業の勤務条件制度等調査  (推計値) 定年制の状況               00020     人事院
# 1  0003288323  00020111  民間企業の勤務条件制度等調査  (推計値) 定年制の今後の変更予定の状況  00020     人事院

[付1-4] CSVファイルに出力

URLのlimit=1000に変更して、1,000件の統計表情報を取得します。そして、取得したデータをCSVファイルに出力します。

df.to_csv('list.csv')

CSVファイルを確認すると、各データのIDやタイトルが確認できます。

id stat_id stat_name title gov_code gov_name
0003288322 00020111 民間企業の勤務条件制度等調査 (推計値) 定年制の状況 00020 人事院
... ... ... ... ...
0003354588 00100101 情報化社会と青少年に関する調査 親 Q6 [カード4] 携帯電話もPHSも使わない理由は何ですか。次の中から、あてはまるものをいくつでもあげてください。(M.A.) 家族の就労状況 00100 内閣府

データは1,000件だけでなく、まだまだ沢山あります。APIでキーワード検索等の絞り込みも行えますが、ブラウザで確認した方が楽です。

*1:200 DegreesによるPixabayからの画像

e-Statの使い方(政府の統計データを見る)

f:id:predora005:20210107001006p:plain
*1

政府統計の総合窓口(e-Stat)」は政府の統計データが閲覧できるサイトです。公式の利用ガイドには次のように書かれています。

政府統計の総合窓口(e-Stat)は、各府省が公表する統計データを一つにまとめ、統計データを検索したり、地図上に表示できるなどの、たくさんの便利な機能を備えた政府統計のポータルサイトです。

職種別の平均年収、人口ピラミッド、人口密度分布といったデータを閲覧できます。

f:id:predora005:20210105121141p:plain

f:id:predora005:20210105214843p:plain

f:id:predora005:20210105231621p:plain

数多くのデータがあり、様々な形式で表示したりダウンロードできます。今回はe-Statの使い方と、どのようなデータがあるのか概要をまとめました。

[1] 基本的な使い方

[1-1] データを探す

データの探し方は色々ありますが、まずは分野から探してみます。

f:id:predora005:20210104211147p:plain

分野は17種類に分かれています。皆さんが想像するような主要な統計データは一通り揃っています。今回は「労働・賃金」分野の「民間給与実態統計調査」を見てみます。

f:id:predora005:20210104211159p:plain

次の画面から「データベース」を選択し「年次」「2016年」と選択していくと、各統計表を選ぶ画面に進みます。

f:id:predora005:20210104213725p:plain

f:id:predora005:20210104214345p:plain

f:id:predora005:20210104214402p:plain

たくさんの統計表が並んでいます。その中から「給与所得者数・給与額・税額 業種別」の「DB」を選択します。

f:id:predora005:20210104211228p:plain

すると、表形式でデータが表示されます。

f:id:predora005:20210104211242p:plain

[1-2] データを絞る

列が多いので、表示する列を絞り込みます。[表示項目選択]を押して項目の選択を行っていきます。

f:id:predora005:20210104215516p:plain

まずは「1/3 表章項目」を「給与所得者数(年間月平均)」と「給与額(平均)」に絞ります。

f:id:predora005:20210104215530p:plain

「3/3 年」は「2016年」のみに絞ります。

f:id:predora005:20210104215541p:plain

これで少し見やすくなりました。

f:id:predora005:20210104215554p:plain

[1-3] グラフを表示する

[グラフ表示]を押すとグラフが表示されます。ただ、このままでは分かりにくいので表示する項目を変更します。

f:id:predora005:20210105105827p:plain

まずは「合計」を表示項目から外します。

f:id:predora005:20210105110022p:plain

次に給与額(平均)のチェックを外し「給与所得者数(年間月平均)」のみ表示するようにします。

f:id:predora005:20210105110217p:plain

これで少しは見やすくなりました。

f:id:predora005:20210105120516p:plain

次は棒グラフを縦向きに変更し、業種を基準軸にします。

f:id:predora005:20210105120554p:plain

これで見るに耐えうる表示になりました。製造業がもっとも人数が多く、電気・ガス・熱供給・水道業がもっとも少ないと分かります。文字が見切れているのは何とも出来ませんでした。

f:id:predora005:20210105120853p:plain

同じ要領で業種ごとの給与額を見てみます。

f:id:predora005:20210105121113p:plain

単位は千円です。電気・ガス・熱供給・水道業がもっとも給与が高く、800万円超えです。宿泊業・飲食サービス業がもっとも低く、150万くらいです。恐らく、パートの方も含んでいるのでしょう。

f:id:predora005:20210105121141p:plain

[2] 統計ダッシュボードを使う

次は[グラフ]をクリックして、統計ダッシュボードを使います。

f:id:predora005:20210105214815p:plain

統計ダッシュボードはe-Statとは別ページに飛びます。

f:id:predora005:20210105214831p:plain

人口ピラミッドを表示すると、いい感じに表示されます。調査をした時点を変えたり、都道府県別に表示したりもできます。

f:id:predora005:20210105214843p:plain

次は[地域の見える化]を選択し「世界と日本のすがた」を見てみます。

f:id:predora005:20210105215720p:plain

2020年の各国の人口が表示されました。表示する国を選ぶことは出来ないようです。

f:id:predora005:20210105215335p:plain

アニメーションを再生させて、時系列の変化を見ることもできます。

f:id:predora005:20210105215350p:plain

人口以外にも「完全失業率」「国内総生産」を見ることも可能です。

f:id:predora005:20210105215403p:plain

続いて「地域のレーダーチャート・ランキング」を見てみます。

f:id:predora005:20210105221908p:plain

デフォルトでは東京都のレーダーが表示されます。

f:id:predora005:20210105221943p:plain

表示する項目は変更できます。項目は40以上あります。

f:id:predora005:20210105222042p:plain

また、各項目についてランキングを表示することもできます。

f:id:predora005:20210105222057p:plain

[3] 時系列表を見る

今度は「時系列表」を見てみます。

f:id:predora005:20210105222537p:plain

分野と表示できる項目が表示されます。

f:id:predora005:20210105222544p:plain

項目を選択すると、時系列表が表示されました。

f:id:predora005:20210105222551p:plain

[4] 統計GISを使う

続いて[地図]をクリックし「地図で見る統計」を開きます。

f:id:predora005:20210105223849p:plain

中段の「地図で見る統計 (jSTAT MAP)」をクリックします。

f:id:predora005:20210105223855p:plain

地図が開きました。ここから色々な作業を行っていきます。

f:id:predora005:20210105223901p:plain

[4-1] 統計グラフ作成

右下の[統計図作成]をクリックするとメニューが表示されます。その中から[統計グラフ作成]を選択します。

f:id:predora005:20210105231555p:plain

ダイアログが表示されますので「調査名」「年」「集計単位」を選択していきます。

f:id:predora005:20210105231603p:plain

今回は「国勢調査」「2015年」「都道府県」を選択しました。その中からさらに「人口性比、密度」「密度(人口総数)」を選択し、[指標選択]をクリックします。

f:id:predora005:20210105231608p:plain

すると、下段に「密度(人口総数)」が追加されます。他のデータも追加できますが今回はこの状態で[次へ]をクリックします。

f:id:predora005:20210105231613p:plain

集計単位と集計範囲はそのままの状態で[集計開始]をクリックします。

f:id:predora005:20210105232717p:plain

無事、都道府県ごとに人口密度が色分けされました。

f:id:predora005:20210105231621p:plain

[4-2] プロット作成

次は地図上にプロットを作成します。

f:id:predora005:20210106214134p:plain

プロット作成には3パターンあります。[ジオコーディング], [緯度経度付きファイル]は事前準備が必要です。今回は何も準備していないので[地図クリック]を選びました。

f:id:predora005:20210106214143p:plain

プロットを作成するためにはグループが必要です。グループには複数のプロットを含むことができます。グループ名を「東京都の駅」とし、アイコンは「ピン型(青)」としました。

f:id:predora005:20210106214147p:plain

[決定]を押すと、地図が再び表示され、地図上をクリックするように促されます。

f:id:predora005:20210106214153p:plain

八王子駅立川駅を登録しました。プロットの作成はこれで終わりです。作成したプロットはこのあとの「エリア作成」で使います。

f:id:predora005:20210106214202p:plain

[4-3] エリア作成

先ほど作成したプロット(八王子駅立川駅)から徒歩15分圏内のエリアを作成します。

f:id:predora005:20210106221106p:plain

グループ名に「駅から15分圏内」を入力します。その他はデフォルトのままでも問題ありません。

f:id:predora005:20210106221116p:plain

次にエリアの作成方法から「到達圏」を洗濯します。

f:id:predora005:20210106221122p:plain

先ほど作成したプロットを使いたいので「到達権(プロットグループ指定)」を選択します。

f:id:predora005:20210106221127p:plain

プロットグループは先ほど作成したグループ「東京都の駅」を選択します。到達圏指定は「徒歩、時速4km、15分圏」に設定します。エリア作成範囲は「すべて」としました。

f:id:predora005:20210106221131p:plain

駅から15分圏内のエリアが、水色のワクで表示されました。

f:id:predora005:20210106221137p:plain

[4-4] 計測

続いては「計測」で距離と面積を計測します。

f:id:predora005:20210106224219p:plain

まずは、上野駅秋葉原駅の直線距離を計測します。距離計測を選択して、上野駅秋葉原駅をクリックすると「1.776km」と表示されました。

f:id:predora005:20210106224227p:plain

続いて、皇居の面積を計測します。面積計測を選択して、地道に皇居周りを選択していきます。結果「2.280km2」と表示されました。実際の面積は約2.3km2らしいので、実際と近い数値になっています。

f:id:predora005:20210106224236p:plain

[4-5] 選択

「選択」を使い、6-1で作成したグラフを選択します。今回はグラフ選択を使用しますが、プロットとエリアの選択も可能です。

f:id:predora005:20210106225843p:plain

宮城県を選択すると、宮城県の人口密度が表示されます。表示される内容は作成したグラフの内容によって変わります。人口密度のグラフを作成したので人口密度が表示されています。

f:id:predora005:20210106225849p:plain

新潟県と愛知県も選択すると、二県の人口密度が追加されました。

f:id:predora005:20210106225856p:plain

[5] 都道府県・市区町村のすがた

次は[地域]をクリックし「都道府県・市区町村のすがた」を見ていきます。

f:id:predora005:20210106234154p:plain

[データ表示]と[地域ランキング]とがありますが、[データ表示]の方を選択します。

f:id:predora005:20210106233918p:plain

すると次の画面が表示されるので、地域選択、表示項目選択の順に行っていきます。

f:id:predora005:20210106233923p:plain

地域区分は「都道府県」とし、北海道と東方地方の県を選択しました。

f:id:predora005:20210106233930p:plain

表示項目選択では、年齢3区分の人口を選択しました。その中から、各区分の総人口に占める割合を選択しました。

f:id:predora005:20210106233938p:plain

北海道・東北地方の、0〜14歳, 15〜64歳, 65歳以上の人口割合が表示されました。この中では秋田県がもっとも少子高齢化が進んでいます。

f:id:predora005:20210106233947p:plain

グラフ表示すると視覚的に表示できます。

f:id:predora005:20210106233953p:plain

グラフ表示は設定を以下のように変更しています。

f:id:predora005:20210106235024p:plain

データ表示については以上です。今度は「地域ランキング」を見てみます。

f:id:predora005:20210106235622p:plain

地域ランキングでは、公共スポーツ施設のランキングを確認しました。

f:id:predora005:20210106235628p:plain

意外なことに北海道が1位、東京都が2位、長野県が3位でした。人口の影響を受けてはいますが、それだけでは無いようです。

f:id:predora005:20210106235634p:plain

終わりに

e-Statの使い方を一通り確認しました。ここで紹介した統計データ以外にも、膨大なデータがe-Statには登録されています。

APIによるデータ取得も可能なので、様々なことに応用できそうです。

*1:200 DegreesによるPixabayからの画像

二輪車業界の株価予想(2020年12月)

f:id:predora005:20201228041731j:plain
<二輪車業界の株価予想(2020年12月)> *1

二輪車業界の株価予想をしました*2

ここでいう二輪車に自転車は含みません。バイクや原付のことと思ってください。

株式投資はくれぐれも自己責任でお願いします。

[1] 二輪車業界の主要プレイヤー

ホンダ、ヤマハ発動機、スズキ、川崎重工です。

2018年度の世界販売台数はホンダが2,023万台、売上は2兆1,000億円で世界第1位です。ヤマハ発動機の世界販売台数は第3位です*3

企業 売上 世界販売台数
ホンダ 2兆1,001億円 2,023万台
ヤマハ発動機 1兆221億円 537万台
スズキ 2,550億円 174万台
川崎重工 3,568億円 55万台

[2] 二輪車の需要

[2-1] 世界の需要

二輪市場は新興国が牽引しています。上から、インド、中国、インドネシアベトナムの順です。中国は自動車への以降期に入ったため減少すると見込まれています。市場全体で見れば、しばらくは緩やかな増加が見込まれます。

二輪車・バイク業界の動向・ランキング等を研究-業界動向サーチ

[2-2] 日本の需要

日本では減少の一途を辿っています。2013年と比べると、2020年は23%減です。かつては、原付第一種(最大30km/h)が販売台数の半分以上を占めていましたが激減しました。中型・大型二輪は原付ほどは減っていません。

2019年度二輪車市場動向調査について | JAMA

理由は原付に対する規制が厳しくなったことと、自転車に取って変わられていることです。電動アシスト付き自転車の売上は年々増えています。また、最近はロードバイクなどのスポーツ自転車も流行っていますね。

[3] 株価の推移

[3-1] 2020年の株価推移

コロナ禍で2月から3月にかけて大きく下落したものの、11月の大統領選挙後に大きく回復しています。通年で見ると年始と年末でほとんど変わっていません。 後述の通り、各社とも減収減益とは言え利益が出ることを受けてのことでしょう(川崎重工以外)。販売台数は回復の兆しを見せています。

f:id:predora005:20201226232406p:plain

[3-2] 2016年以降の株価推移

スズキ以外は減少傾向にあります。各社とも二輪車以外の事業も行っていますので、減少の要因は各社それぞれです。要因についてはこの後見ていきます。

f:id:predora005:20201226233827p:plain

[4] 各社の販売台数推移と内訳

[4-1] ホンダ

二輪事業は9割がアジアを占めています。もう1つの主力事業である、四輪事業においてもアジアが4割を占めており、アジアでの販売台数が重要であると分かります。

f:id:predora005:20201227090549p:plain

販売台数の推移を見ると、コロナ禍で2019年度と2020年度は減少しています。2016年から2018年度で見ると、二輪車の増加率が大きいことが分かります。

f:id:predora005:20201227092642p:plain

ライフクリエーション事業の販売台数は、パワープロダクツ(発電機、耕うん機、芝刈機、除雪機)などで構成されています。

[4-2] ヤマハ発動機

ヤマハ発動機アジアでの二輪車販売台数が8割以上を占めています。

ヤマハ発動機は、マリン事業が二輪車事業に継ぐ主力事業です。マリン事業は、ボートやウォータービークルの販売などを行っています。販売台数ではなく売上高の内訳ですが、こちらは北米が6割を占めています。

f:id:predora005:20201227135016p:plain

販売台数の推移を見ると、近年はやや減少傾向です。ヤマハ発動機の決算は12月なので、新型コロナウィルスの影響は含まれていません。

f:id:predora005:20201227135657p:plain

一方、マリン事業の方は二輪車事業と比較すると堅調です。ただ、2018年から2019年は横ばいなので、成長しているとは言えません。

f:id:predora005:20201227140422p:plain

[4-3] スズキ

スズキも二輪車の販売台数の8割はアジアが占めています。特に、インドでの売上が4割を占めている点が大きな特徴です。

f:id:predora005:20201227164848p:plain

スズキは、四輪事業が主力であり、二輪事業が売上や利益に占める割合は大きくありません(後述)。そのため、スズキの場合は四輪事業の成否が株価に大きく影響します。

販売台数の推移を見ると、コロナ禍の影響を受けています。コロナ以前(2015年度〜2018年度)は、四輪事業・二輪事業ともに販売台数を伸ばしています。

f:id:predora005:20201227165653p:plain

四輪事業はインドでの販売台数が大きく伸びており、日本での販売台数も順調に増えています。

f:id:predora005:20201227170052p:plain

[4-4] 川崎重工

川崎重工は販売台数の地域別内訳は無く、先進国・新興国で別れていました。内訳を見ると他の3社同様に、新興国の販売台数が大きな割合を占めています。

f:id:predora005:20201227193638p:plain

コロナ以前は販売台数が増加してましたが、2019年度はコロナ禍の影響で減少しています。

[5] 各社のセグメント別売上と利益

[5-1] ホンダ

ホンダの売上高の6割は四輪事業が占めています。一方、営業利益は内訳が年度ごとに異なっており、二輪車事業と金融サービス業が安定しています。

f:id:predora005:20201227104404p:plain

世界第1位の販売台数を誇る二輪車事業は、四輪事業と並ぶ利益を上げています。しかし、成長が鈍化していることや、為替影響などもあり年々利益率が低下していることが懸念点です。

[5-2] ヤマハ発動機

売上高の半分はランドモビリティ事業*4が占めており、ついでマリン事業となっています。一方、営業利益はマリン事業が半分を占めており、マリン事業の利益率が高いと分かります。

f:id:predora005:20201227171320p:plain

ヤマハ発動機の決算は12月のため、このデータはコロナ禍の影響を織り込んでいません。最新の決算資料を見ると、当然コロナ禍の影響はあり、2020年12月期は減収減益を見込んでいます。

2019年度実績を見ると、ランドモビリティ事業とマリン事業は減益ですが、これは為替の影響もあります。ロボティクス事業は市況悪化による減益ですが、2019年度実績は概ね前年度と横ばいと言えます。

[5-3] スズキ

スズキは四輪事業が売上高・営業利益ともに9割を占めています。コロナ禍の影響で2019年度は減収減益となっていますが、2018年までは販売台数が伸び続けており順調と言えます。

二輪事業はスズキの場合には売上高に占める割合は低く、利益もゼロに近いです。

f:id:predora005:20201227171916p:plain

スズキも当然新型コロナウィルスの影響を受けています。四輪車の販売台数は全ての地域で減少を見込んでいます。主戦場であるインド・アジアも大きな減少を見込んでいるため、今年度も減収減益も見込んでいます。

[5-4] 川崎重工

川崎重工の事業分野は他3社に比べて多岐に渡っています。その中でも航空宇宙システムが売上・営業利益のおよそ30%を占めていました。

しかし、コロナ禍の影響で航空業界が大打撃を受けていることから、2020年度見通しでは赤字予想となっています。

f:id:predora005:20201228012801p:plain

二輪車事業は、モーターサイクル&エンジンに含まれます。売上高・営業利益ともに2割程度を占めています。コロナ禍により、2019年度は減収減益、2020年度見通しも減収減益です。

その他の事業も減益の見通しとなっており、2020年度は赤字予想です。

まとめ

[6-1] ホンダ

ホンダは二輪車の販売台数で世界第1位です。世界の販売台数の約30%を占めています。四輪事業の規模も大きく、売上高の6割を占めています。また、金融サービス業の利益率が高く、毎年利益を出しています。

懸念点は成長の鈍化です。二輪車のインドでの販売台数は鈍化しており、インドや台湾メーカーも台頭してきています。

いずれ、インドは自動車への以降期に入ります。二輪車の販売台数は横ばいになり、四輪車の販売台数はより増えると予想されます。また、インド以外の新興国での二輪車の販売台数は増えるでしょう。

今後、インドや新興国二輪車と四輪車の販売台数を増やせるかが株価上昇のカギとなりそうです。私はコロナ禍の収束により、2016年〜2017年の株価水準に戻る可能性はあるものの、それ以上の上昇の可能性は低いと見込んでいます。

事業は二輪車・四輪車の2つが主力であり、金融サービス業もホンダ製品販売のリースや融資です。二輪車と四輪車の販売台数増加には限度があるため、大きな株価上昇は無いという予想です。

[6-2] ヤマハ発動機

ヤマハ発動機もホンダ同様にアジアでの二輪車販売台数の増加が重要です。

しかし、先進国を中心としたマリン事業が好調ですし、ロボティクス事業を持っています。今後のロボット需要増加の中で売上を伸ばすことができれば、株価上昇も期待できます。

[6-3] スズキ

4社の中で唯一、2016年1月基準で株価が上昇しているのがスズキです。四輪車事業が9割の会社ですが、その四輪車事業が好調です。新型コロナウィルスの影響もあり2019年度は減収減益です。しかし、新興国でなく日本国内の販売台数も伸びており、利益も出ていることから株価が大きく下がる心配は無さそうです。

電気自動車やシェアライドが普及し始めたときに対抗できるかどうかは疑問です。しかし、普及にはまだしばらく時間がかかりそうです。そのため、コロナ禍の収束により一定の水準まで株価が上昇し、数年間は安定すると予想しています。

[6-4] 川崎重工

川崎重工は、二輪車事業の規模は大きくないものの、多岐に渡る事業で利益を出してきました。1事業がマイナスでも他事業で補えていました。しかし、コロナ禍により稼ぎ頭であった航空宇宙システムが大きな減益(前年比-500億円以上)となり、今年度は赤字となりそうです。

f:id:predora005:20201228015920p:plain

また、気になる点は借入が増えていることです。自己資本比率は25%前後でしたが、20%近くまで低下する見通しです。

コロナ禍の影響はしばらく続きそうです。そのため、航空業界の回復にはしばらく時間がかかりそうです。航空宇宙システムの回復も遅れると想定されるため、会社全体の利益回復には時間がかかりそうです。

そのため、株価もしばらくは低調な状態が続くと予想されます。

終わりに

今回は二輪車業界の決算資料と株価を元に、今後の株価を予想してみました。

自分自身、二輪車業界に詳しいわけでもなく、二輪車に乗るわけでもありませんでした。なので、決算資料を見て業界のことが少しわかっただけでも収穫でした。

この予想が当たるのか外れるのか楽しみに待ちたいと思います。願わくば、コロナ禍が早く収束し、予想を裏切って各社の業績が回復して欲しいです。

参考資料

Honda | 投資家情報 | IR資料室 | 決算関連資料

決算・発表資料 - 株主・投資家情報 | ヤマハ発動機

投資家向け説明会|スズキ

決算説明資料 | IRライブラリ | 川崎重工業株式会社

*1:Free-PhotosによるPixabayからの画像

*2:2020年12月末の情報で予想しています

*3:日経業界地図 2020年版より

*4:二輪車、オフロードビークル電動アシスト自転車など

GitHubでパスワード認証が廃止されるので二要素認証とトークン認証の設定方法をまとめた

GitHubのパスワード認証が2021/08/13以降、受け付けなくなるそうです。まだ期限まで時間はありますが、今のうちに対処しておくことにしました。

gigazine.net

やることは2点です。

  • 二要素認証を有効にする
  • トークンを作成する

[1] 二要素認証を有効にする

[1-1] 設定画面へ移動する

GitHubにブラウザでアクセスし[Settings]を選択します。

f:id:predora005:20210131201353p:plain

[Account security]を選択します。

f:id:predora005:20210131201358p:plain

画面中央のTwo-factor authenticationの中から[Enable two-factor authentication]をクリックします。

f:id:predora005:20210131201403p:plain

パスワードを入力し、次の画面に進みます。

f:id:predora005:20210131201414p:plain

[1-2] 二要素認証の方法を選択する

続いて、二要素認証の方法を選択します。アプリSMSの2種類から選択できます。

アプリは、スマホなどのモバイル端末のアプリで認証コードを取得する方法です。私は「Google Authenticator」を使用しています。

SMSは、携帯のショートメッセージに認証コードが送られてくる方法です。

私はアプリの方を選んだので、アプリの設定方法を紹介します。

f:id:predora005:20210131201417p:plain

[Set up using an app[を選択すると、リカバリーコードが表示されます。リカバリーコードは二要素認証が行えなくなった場合に使用します。この画面を消すと取得できなくなるので[Download]や[Copy]を用いて保存しておきます。

f:id:predora005:20210131201436p:plain

次の画面では、QRコードが表示されます。アプリでQRコードをスキャンして、認証情報をアプリに登録します。登録できたら、アプリに表示された6ケタの認証コードを入力します。入力後[Enable]を押せば、無事に設定完了です。

f:id:predora005:20210131201441p:plain

[2] トークンを作成する

二要素認証と同様にAccount settings画面に移動し、[Developer settings]を選択します。

f:id:predora005:20210131201459p:plain

[Personal access tokens]を選択します。

f:id:predora005:20210131201504p:plain

[Generate new token]をクリックします。

f:id:predora005:20210131201507p:plain

[Note]に何に使用するトークンなのかを入力し、[Select scopes]でトークンの適用範囲を選択します。私はリポジトリへのアクセスにのみ使用するため「repo」を選択しました。

f:id:predora005:20210131201510p:plain

次の画面に進むとトークンが表示されます。この画面から移動すると二度とトークンが確認できないので、保存しておきましょう。

f:id:predora005:20210131201515p:plain

[3] 試しにpushしてみる

従来のパスワード認証でpushしてみます。すると、認証エラーで失敗しました。

$ git push
Username for 'https://github.com': {アカウント名}
Password for 'https://{アカウント名}@github.com': 
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/{アカウント名}/{リポジトリ名}/'

続いて、トークン認証を試します。トークン認証ではパスワード欄にトークンを入力します。

$ git push
Username for 'https://github.com': {アカウント名}
Password for 'https://{アカウント名}@github.com': 
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 731 bytes | 731.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To https://github.com/{アカウント名}/{リポジトリ名}/
   ... (省略) ...

トークン認証で、pushできました。

参考文献

鉄道業界の株価予想(2020年12月)

f:id:predora005:20201219140822j:plain
<鉄道業界の株価予想(2020年12月)> *1

前回までに行ったスクレイピングで得た情報も取り入れつつ、株価予想をしていきます。

コロナウィルスの影響を大きく受けている鉄道業界の株価予想をします*2

株式投資はくれぐれも自己責任でお願いします。

[1] 2020年の株価推移

コロナウィルスの影響で株価は大きく下落しています。

特に新幹線事業を行っているJR九州JR東日本JR東海JR西日本の下落幅が大きいです。 それ以外は各社に依りけりです。東急は年初と比較して40%近く下落していますが、他社は最大30%弱の下落幅に留まっています。

f:id:predora005:20201219120547p:plain

[2] JR東日本の状況

JR東日本の決算情報から、新幹線事業を持つ企業の状況を見ていきます。

決算説明会:JR東日本

[2-1] セグメント別の収益

鉄道会社は運輸収入*3だけで稼いでるわけではありません。不動産事業やサービス事業でも稼いでいます。例えば、JR東日本は駅ビル・オフィスビル・ホテルなどの不動産を所持しています。また、アトレやエキュートなどの小売業も積極的に行っています。

コロナウィルスの影響が無い、2019年3月期の決算情報から収益の割合を見てみます。運輸事業が営業収益(売上)・営業利益ともに 70%近くを占めています。

f:id:predora005:20201219120830p:plain

運輸事業の中での内訳を見ると、在来線が6割、新幹線が3割程度です。つまり、JR東日本の収益の40%は在来線、20%は新幹線ということです。

f:id:predora005:20201219121223p:plain

[2-2] 2020年第2四半期の実績

2020年4月〜9月の実績は、営業収益が50%減です。特に新幹線の輸送量は前年度比70%減であり、コロナウィルスの影響が顕著です。不動産事業は前年同期比と比較して30%減、サービス事業は50%減となっています。

2020年通期の純利益は、4,000億円マイナスの予想です。コロナウィルスの影響が軽減されれば業績は戻っていくと思いますが、しばらくは厳しい状況が続きそうです。2020年3月期の純利益が約2,000億円ですから、かなり大きいマイナスです。

f:id:predora005:20201219141706p:plain

[3] 近鉄GHDの状況

続いて、JR系と比較して株価の落込みが小さい、近鉄GHDの決算状況を見ていきます。

近鉄グループホールディングス株式会社|株主・投資家情報|IR資料|決算説明会

[3-1] セグメント別の収益

JR東日本と同様に、コロナウィルスの影響が無い、2019年3月期の決算情報から収益の割合を見てみます。運輸事業が占める比率は、営業収益が17%, 営業利益が49%です。JR東日本の68%, 70%と比較すると、運輸事業への依存度は低いことが分かります。

f:id:predora005:20201219130044p:plain

[3-2] 2020年第2四半期の実績

2020年4月〜9月の実績は、営業収益が54%減です。2020年通期の純利益は、310億円マイナスの予想です。50%減収という点は、JR東日本と変わりません。

f:id:predora005:20201219141841p:plain

セグメント別の営業収益を見ると、運輸が40%減、不動産が20%、流通が25%減、ホテル・レジャーが90%減です。

運輸の影響はJR東日本と比べて小さいのですが、ホテル・レジャーの減益がかなり大きいと予想されています。ホテル・レジャーの営業利益は360億円のマイナス予想になっています。

[4] 2016年からの株価推移

2016年1月4日の株価を基準とした、株価の上昇率はグラフの通りです。

全体的にみると、2020年初頭までは20%程度上昇し、2020年に入ってから大きく下落しています。

2016年1月から2020年1月までの間に、TOPIXは20%近く上昇しました。 TOPIXと同じ上昇率なので、鉄道業界が目立って浮き沈みはしていないと言えます。

f:id:predora005:20201219133558p:plain

[5] 鉄道輸送量の推移

政府の統計ページ e-Statより、鉄道輸送量の年度別推移を見てみます。緩やかに上昇していましたが、2019年度に減少に転じています。日本の人口は減少し続けているので、今後大きく増えていくことは期待できません。緩やかに減少していくでしょう。

f:id:predora005:20201220233506p:plain

鉄道業界の主な収益は運輸収入です。輸送量が減れば運輸収入も減りますので、鉄道業界が大きく成長することは見込めないわけです。成長するとしたら別セグメントが成長するか海外展開でしょう。

[6] 今後の株価予想

しばらくは低調な状態が続きそうです。本格的に回復するのは、コロナウィルスのワクチン接種が始まってからでしょう。

JR系と民鉄で比較すると、民鉄の方が低迷が続くと思います。ホテル・レジャー事業のマイナスが大きいからです。数年間は国内旅行の減少、インバウンドの減少は戻らないと予想しています。

一方、JR系はコロナウィルスの影響が落ち着けば、運輸収入はだいぶ戻るでしょう。株価も元に戻っていくと予想できます。ただし、今後大きな成長が見込める業界ではありません。株価が上昇するとしても、日経平均TOPIXと近い上昇率で推移すると思われます。

*1:Martin WinklerによるPixabayからの画像

*2:2020年12月末の情報で予想しています

*3:電車に乗る際に我々が支払う運賃が主

無料のt4g.microインスタンスでnumpy, pandas, matplotlibのインストールにハマった

AWSのArmベースインスタンスt4g.micro、2021年3月31日まで無料トライアル中です。無料で使えるやったと思っていたら思わぬところで引っかかりました。

[0] 前提条件

OSはAmazon Linux2、python3とpip3はインストール済みです。

$ python3 -V
Python 3.7.9
$ pip3 -V
pip 9.0.3 from /usr/lib/python3.7/site-packages (python 3.7)

[1] numpyのインストールに失敗する

$ pip3 install numpy --user
...
ModuleNotFoundError: No module named 'Cython'
...

Cythonが無いと怒られます。対処法はcythonのインストールです。

$ pip3 install cython --user

[2] numpyのインストールに時間がかかる

理由は、ソースをビルドしているからです。

$ pip3 install numpy --user
Collecting numpy
  Using cached https://files.pythonhosted.org/packages/51/60/3f0fe5b7675a461d96b9d6729beecd3532565743278a9c3fe6dd09697fa7/numpy-1.19.5.zip
Installing collected packages: numpy
  Running setup.py install for numpy ... done
Successfully installed numpy-1.19.5

また、t4g.microのスペックはvCPU=2、メモリ=1(GiB)と決して高くないため、より時間がかかります。

[3] pandasがout of memoryでインストールできない

pandasもnumpyと同様に、ソースをビルドしてインストールしようとします。

pip3 install pandas --user
Collecting pandas
  Downloading https://files.pythonhosted.org/packages/11/1c/b0bc154996617eae877ff267fcf84e55e6c6808dbade0da206f0419dd483/pandas-1.2.1.tar.gz (5.5MB)
    100% |████████████████████████████████| 5.5MB 273kB/s 
...
  Running setup.py install for pandas ... error
...
    as: out of memory allocating 4064 bytes after a total of 163106816 bytes
...

t4g.microのメモリ=1(GiB)では、pandasをソースからビルドするのには足らなかったようです。

有効な対応策が見つからなかったため、t4g.smallでビルドしました。

[4] matplotlibのインストールに失敗する

matplotlibに必要な「kiwisolver」のインストールに失敗します。

$ pip3 install matplotlib --user
Collecting matplotlib
  Downloading https://files.pythonhosted.org/packages/7b/b3/7c48f648bf83f39d4385e0169d1b68218b838e185047f7f613b1cfc57947/matplotlib-3.3.3.tar.gz (37.9MB)
    100% |████████████████████████████████| 37.9MB 39kB/s 
Collecting cycler>=0.10 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/f7/d2/e07d3ebb2bd7af696440ce7e754c59dd546ffe1bbe732c8ab68b9c834e61/cycler-0.10.0-py2.py3-none-any.whl
Collecting kiwisolver>=1.0.1 (from matplotlib)
  Downloading https://files.pythonhosted.org/packages/90/55/399ab9f2e171047d28933ae4b686d9382d17e6c09a01bead4a6f6b5038f4/kiwisolver-1.3.1.tar.gz (53kB)
    100% |████████████████████████████████| 61kB 13.0MB/s 
...
    ValueError: bad marshal data (unknown type code)
    
    During handling of the above exception, another exception occurred:
...
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-7wgyhm4y/kiwisolver/

対応策は、pipを最新にすることです。

$ sudo pip3 install -U pip
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting pip
  Downloading https://files.pythonhosted.org/packages/de/47/58b9f3e6f611dfd17fb8bd9ed3e6f93b7ee662fb85bdfee3565e8979ddf7/pip-21.0-py3-none-any.whl (1.5MB)
    100% |████████████████████████████████| 1.5MB 916kB/s 
Installing collected packages: pip
  Found existing installation: pip 9.0.3
    Uninstalling pip-9.0.3:
      Successfully uninstalled pip-9.0.3
Successfully installed pip-21.0
$ source ~/.bash_profile

終わりに

最終的には無事解決できましたが、意外なところでハマってしまいました。

日本株の株価をpythonでスクレイピングを使って取得しmatplotlibで可視化する(2)

f:id:predora005:20201205193159j:plain
*1

前回の続きです。前回は単一銘柄の株価をスクレイピングで取得しmatplotlibで可視化しました。今回は複数銘柄の株価を取得し比較していきます。

predora005.hatenablog.com

f:id:predora005:20201206204240p:plain

[1] 複数銘柄の株価取得

get_stock_price, astype_stock_price, add_moving_average_stock_price前回のソースコードを関数化したものです。各銘柄に対してスクレイピングを行い、取得した結果をDataFrameの末尾に結合していきます。

import time
import pandas as pd

codes = { 'JR東日本': 9020, 'JR西日本': 9021 }
start_year, end_year = 2019, 2020
df = None

for name in codes.keys():
    
    # 指定した証券コードの決算情報を取得する。
    code = codes[name]
    df_tmp = get_stock_price(code, start_year, end_year)
    
    # 株価情報のデータタイプを修正する
    df_tmp = astype_stock_price(df)
    
    # 株価情報に移動平均を追加する
    df = add_moving_average_stock_price(df)
    
    # 銘柄名を追加し、MultiIndexにする。
    df_tmp['銘柄'] = name
    df_tmp = df_tmp.set_index('銘柄', append=True)
    
    # 2回目以降は既存のDataFrameの末尾にデータを追加
    if df is None:
        df = df_tmp
    else:
        df = df_tmp.append(df)
    
    # 1秒ディレイ
    time.sleep(1)

# indexを入れ替える
df = df.swaplevel('銘柄', '日付').sort_index()

結果、次のデータが得られました。

始値 高値 安値 終値 出来高 終値調整 5日移動平均 25日移動平均 75日移動平均
銘柄 日付
JR東日本 2019-01-04 9675.0 9820.0 9627.0 9731.0 1337200.0 9731.0 NaN NaN NaN
2019-01-07 9918.0 10065.0 9915.0 10030.0 887500.0 10030.0 NaN NaN NaN
... ... ... ... ... ...
JR西日本 2020-12-03 5085.0 5249.0 5077.0 5233.0 1869000.0 5233.0 4986.8 4907.92 5172.11
2020-12-04 5299.0 5414.0 5257.0 5317.0 1745900.0 5317.0 5038.2 4932.32 5173.95

[2] 可視化

[2-1] 2020年以降のデータを抽出

DataFrameをMultiIndexしたことにより、日付による抽出方法が少し変わっています。pd.IndexSliceを用いて抽出します。

# 2020/01/01以降のデータを抽出
df = df.loc[pd.IndexSlice[:, '2020-01-01':], :]
# (前回) df = df['2020-01-01':]

下記記事を参考にさせてもらいました。

pandasのMultiIndexから任意の行・列を選択、抽出 | note.nkmk.me

[2-2] 株価の可視化

まずは、終値をそのまま折れ線グラフで可視化してみます。抽出したデータを折れ線グラフで可視化します。

f:id:predora005:20201206204351p:plain

# Figureを取得
fig = plt.figure(figsize=(10, 4))

# 銘柄名のリスト取得
brand_names = list(df.index.unique('銘柄'))

# 銘柄別に折れ線グラフで表示する
for i, brand_name in enumerate(brand_names):
    
    # Axesを取得
    ax = fig.add_subplot(1, 2, i+1)
    
    # 表示するデータを抽出
    df_brand = df.loc[brand_name,]
    x = df_brand.index  # 日付
    y = df_brand['終値']
    
    # 折れ線グラフ表示
    label = '{0:s}-終値'.format(brand_name)
    ax.plot(x, y, label=label, linewidth=2.0)
    
    # 移動平均の折れ線グラフを追加
    average_columns = ['5日移動平均', '25日移動平均', '75日移動平均']
    for column in average_columns:
        x = df_brand.index  # 日付
        y = df_brand[column] # 移動平均
        label = '{0:s}-{1:s}'.format(brand_name, column)
        ax.plot(x, y, label=label, linewidth=1.0)

    # 目盛り線を表示
    ax.grid(color='gray', linestyle='--', linewidth=0.5)
    
    # 凡例を表示
    ax.legend()
    
    # グラフのタイトルを追加
    ax.set_title(brand_name)
    
# 不要な余白を削る
plt.tight_layout()

# グラフを表示
fig.show()

[2-3] 値上がり率の可視化

株価は発行済株数によって変わるので単純比較はできません。そこで、ある日付を基準とした値上がり率で比較してみます。

f:id:predora005:20201206204550p:plain

2020/01/06を基準とした比率で言うと、JR西日本の方が株価が大きく下落しています。

# 基準日を設定
ref_date = datetime.date(2020, 1, 6)
ref_date_str = ref_date.strftime('%04Y-%02m-%02d')

# FigureとAxesを取得
fig = plt.figure()
ax = fig.add_subplot(1,1,1)

# 銘柄別に値上がり率を計算
for brand_name in brand_names:
    
    # 指定銘柄のデータを取得
    df_brand = df.loc[brand_name,]
    
    # 値上がり率を計算
    base_price = df_brand.loc[ref_date_str,'終値']  # 基準日の終値
    rate = df_brand['終値'] / base_price - 1        # 値上がり率
    
    # 表示するデータを抽出
    x = df_brand.index  # 日付
    y = rate
    # 折れ線グラフを表示
    ax.plot(x, y, label=brand_name)
    
# 目盛り線を表示
ax.grid(color='gray', linestyle='--', linewidth=0.5)

# 凡例を表示
ax.legend()

# Y軸の単位をパーセント表示に設定
ax.yaxis.set_major_formatter(mpl.ticker.PercentFormatter(1))

# グラフのタイトルを追加
ax.set_title('値上がり率')

# グラフを表示
fig.show()

期間をもう少し長く取ると、JR西日本は2019年〜2020年にわたって株価が大きく上昇していました。そのため、2020年の下落幅も大きかったことがわかります。

f:id:predora005:20201206205046p:plain

[2-4] 株式分割に注意

株式分割等で株価が急激に変わった場合は補正が必要です。例えば、株価¥10,000だった銘柄が株式分割で1株を10株に分割すると、株価は¥1,000になります。

株価は10分の1になりますが、1株あたりの価値は変わりません。この場合、株式分割後の株価を10倍にする補正が必要でしょう。

[2-5] 補足: DataFrameに値上がり率を追加

ちなみに、元のDataFrameに値上がり率を追加するためには以下のようにします。

# 値上がり率の列を用意
df['値上がり率'] = np.nan
    
for brand_name in brand_names:
    ...(中略)...

    # 値上がり率をDataFrameに追加
    #   (rateはSeries. そのまま代入するとindexが合わないためNG)
    df.loc[(brand_name, ), '値上がり率'] = rate.values

終わりに

株価をスクレイピングで取得し、複数銘柄間の比較を行ました。上記では'JR東日本'と'JR西日本'の2銘柄のみ扱いましたが、銘柄数を増やすことは用意です。いちど仕組みを作ってしまえば応用することは難しくありません。

f:id:predora005:20201206211135p:plain

そもそもスクレイピングを始めた目的は、株式投資のために企業分析を行うことでした。より詳しい分析を行うためには各企業の決算情報なども見ないと足りないなと感じました。

ただ、今回行ったことは分析の取っ掛かりとしては悪くありませんでした。その業界全体の傾向を見る場合や、その業界のなかで他と値動きが異なる企業を探す場合に活用できそうです。

*1:Gerd AltmannによるPixabayからの画像