地点ごとのアドレス数(「賑わい度」)の描画

WebページにおけるJavaScriptモジュールでの描画は、モニタでの閲覧には便利だが、キャプチャした図は印刷物にするには品質が悪すぎる。

同じデータを、印刷に適したスケーラブル画像をpythonで描画する。

印刷用ファイルを作るときは、plt.show()の前にファイルへの出力を書く。(スケーラブル画像svgが好ましい。)

クラススクリプトは一番下にある。最初にこれを実行しておく。

In [32]:
points = ["kofu25", "kofu26", "kofu27"]
plotHourlyData(points, "20190925", "a")
In [33]:
points = ["kofu25", "kofu26", "kofu27"]
plotDailyData(points, "20190825", "20190924","a")
In [34]:
points = ["kofu25", "kofu26", "kofu27"]
plotDailyData(points, "20190825", "20190924","g")
In [35]:
points = ["ff02", "ff03", "ff04"]
plotDailyData(points, "20190825", "20190924","a", "ff")
In [4]:
# 参考
# 地点IDと名前
import pandas as pd
filename = {"kofu": "/var/www/html/kofu/kofu_position.csv",
            "fuefuki": "/var/www/html/ff/sensor_points.csv",
            "hakushu": "/home/toyoki/public_html/hakushu/points_hakushu.csv",
            "ttri": "/home/toyotamngr/csv/toyota/sensor_points.csv"}
df = pd.read_csv(filename['kofu'])
df
Out[4]:
センサ名 lat log 地点名 カテゴリ 短縮名
0 kofu1 NaN NaN NaN NaN NaN
1 kofu2 35.658933 138.571024 三枝豆店 中央 三枝豆店
2 kofu3 35.660988 138.571165 風月堂 中央 風月堂
3 kofu4 35.670632 138.565893 永田楽器 北口・朝日町 永田楽器
4 kofu5 35.662019 138.571818 文化のるつぼ Hechima 丸の内 るつぼ
5 kofu6 NaN NaN NaN NaN NaN
6 kofu7 35.666474 138.567104 ライフインナカゴミ 丸の内 ライフイン
7 kofu8 35.669087 138.566179 オスカー本社・朝日店 北口・朝日町 オスカー
8 kofu9 35.663483 138.568223 防災新館1F 丸の内 防災新館
9 kofu10 35.660508 138.571015 河野スポーツ 中央 河野
10 kofu11 35.658980 138.569654 内藤セイビドー眼鏡店 中央 内藤セイビドー
11 kofu12 35.665457 138.567812 立ち食い焼肉 鷹の 丸の内 鷹の
12 kofu13 35.659908 138.571535 銀座通り東(ブラザー文房具) 中央 銀座通り東
13 kofu14 35.666835 138.571457 甲州夢小路 北口・朝日町 夢小路
14 kofu15 NaN NaN NaN NaN NaN
15 kofu16 35.662705 138.570433 甲府クラフトラボ 丸の内 クラフトラボ
16 kofu17 35.661394 138.568810 ダン珈琲店 中央 ダン
17 kofu18 35.662433 138.569498 カフェ・キュイエール 丸の内 キュイエール
18 kofu19 35.660883 138.570182 きぬや 中央 きぬや
19 kofu20 35.660050 138.569150 そば処 奥義 中央 奥義
20 kofu21 35.671693 138.566729 玉屋 北口・朝日町 玉屋
21 kofu22 35.665733 138.568327 奥藤本店 丸の内 奥籐
22 kofu23 35.665305 138.567282 六曜館珈琲店 本店 丸の内 六曜館
23 kofu24 35.660092 138.570098 銀座通り西(ルパンザバール前) 中央 銀座通り西
24 kofu25 35.666321 138.568691 甲府駅南口 甲府駅周辺 駅南口
25 kofu26 35.667769 138.570091 藤村記念館 甲府駅周辺 藤村
26 kofu27 35.667481 138.569165 甲府駅北口コンコース 甲府駅周辺 駅北口
27 kofu28 35.666682 138.567703 甲府駅南口第1駐輪場 甲府駅周辺 第1駐輪場
28 kofu29 35.666348 138.570488 甲府駅南口第2駐輪場 甲府駅周辺 第2駐輪場
29 kofu30 35.658877 138.569747 オリンピック通り 中央 オリンピック通り
30 kofu31 35.657720 138.569734 甲府商工会義所 中央 商工会議所
31 kofu32 35.668393 138.555370 エスティケイ 飯田 エスティケイ
In [23]:
# 処理全体のクラススクリプト

json_root = "https://8tops.yamanashi.ac.jp/"

import json
import requests
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.family'] = 'IPAPGothic'  # 全体のフォントを設定

def plotHourlyData(points, day, addr='a', area='kofu', dev="all"):
    resp = requests.get(json_root + area +"/"
                        + "getHourlyCounts.php"
                        + "?sdate=" + day
                        + "&edate=" + day
                        + "&addr=" + addr)
    json_dict = resp.json()
    plot_data = {}
    # プロットするデータをDataFrameに: 数値に変換する必要があることに注意
    pointAttrib = getPointAttribute(area)
    for pt in points:
        if not pt in json_dict.keys():
            continue
        plot_data[pointAttrib[pt]['短縮名']] = list(
            map(float, json_dict[pt][day]['hourly']))
    df4plot = pd.DataFrame(plot_data)

    # プロット
    fig = plt.figure(figsize=(6, 4))
    ax = fig.add_subplot(1, 1, 1)
    ax = df4plot.plot(ax=ax, fontsize=12)
    # 凡例は外側に固定
    ax.legend(fontsize=12, loc='center left',
              bbox_to_anchor=(1.05, 0.5), borderaxespad=0)
    ax.set_title("地点アドレス数 (" + day + ")",
                 fontsize=12)
    ax.set_xlabel("時間", fontsize=12)
    ax.set_ylabel("アドレス数", fontsize=12)
    plt.show()

def plotDailyData(points, sday, eday, addr='a', area='kofu'):
    """
    指定したエリア内のpointsのデータを作図
    points: 地点の単純なリスト
    """
    resp = requests.get(json_root + area + "/"
                        + "getHourlyCounts.php"
                        + "?sdate=" + sday
                        + "&edate=" + eday
                        + "&addr=" + addr)
    json_dict = resp.json()
    plot_data = {}
    pointAttrib = getPointAttribute(area)
    
    for pt in json_dict:
        if not pt in points:
            continue
        plot_data[pointAttrib[pt]['短縮名']] = {}
        for day in json_dict[pt]:
            day_by_datetime = datetime.strptime(day, "%Y%m%d")
            plot_data[pointAttrib[pt]['短縮名']][day_by_datetime] = 0
            for h in json_dict[pt][day]['hourly']:
                plot_data[pointAttrib[pt]['短縮名']][day_by_datetime] += int(h)
    df4plot = pd.DataFrame(plot_data)
    # プロット
    fig = plt.figure(figsize=(6, 4))
    ax = fig.add_subplot(1, 1, 1)
    ax = df4plot.plot(ax=ax, fontsize=12)
    # 凡例は外側に固定
    ax.legend(fontsize=12, loc='center left',
              bbox_to_anchor=(1.05, 0.5), borderaxespad=0)
    ax.set_title("地点アドレス数 (" + sday + "〜" + eday + ")",
                 fontsize=12)
    ax.set_xlabel("日", fontsize=12)
    ax.set_ylabel("アドレス数", fontsize=12)
    plt.show()
    
def plotDailyDataByGroup(points, sday, eday, addr='a', area='kofu', dev="all"):
    """
    何枚もの図を並べて書きたい場合にも対応
    
    points: [{group_name: グループ名, points: [point1, point2, ...]}, ...]
    
    """
    resp = requests.get(json_root + area + "/"
                        + "getHourlyCounts.php"
                        + "?sdate=" + sday
                        + "&edate=" + eday
                        + "&addr=" + addr
                        + "&dev=" + dev) # devはWi-Fiデバイスを表すがkofuでは効力がない
    json_dict = resp.json()
    plot_data = {}
    pointAttrib = getPointAttribute(area)
    
    fig_col = 2
    fig_row = int(len(points) / fig_col + 1)
    fig = plt.figure(figsize=(8*fig_col, 5*fig_row))
    # 余白を設定
    plt.subplots_adjust(wspace=0.6, hspace=0.3)
 
    fig_num = 0
    
    for group in points:
        plot_data = {}
        for pt in group['points']:
            if not pt in json_dict:
                continue
            plot_data[pointAttrib[pt]['短縮名']] = {}
            for day in json_dict[pt]:
                day_by_datetime = datetime.strptime(day, "%Y%m%d")
                plot_data[pointAttrib[pt]['短縮名']][day_by_datetime] = 0
                for h in json_dict[pt][day]['hourly']:
                    plot_data[pointAttrib[pt]['短縮名']][day_by_datetime] += int(h)
        df4plot = pd.DataFrame(plot_data)
        df4plot.replace(0, np.nan, inplace=True)
        # print(df4plot)
        # プロット
        fig_num +=1
        sub_fig = fig.add_subplot(fig_row, fig_col, fig_num)
        ax = df4plot.plot(ax=sub_fig, fontsize=10)
        # 凡例は外側に固定
        ax.legend(fontsize=12, loc='center left',
                   bbox_to_anchor=(1.05, 0.5), borderaxespad=0)
        ax.set_title(group['group_name'] + " (" + sday + "〜" + eday + ")",
                     fontsize=12)
        # ax.set_xlabel("日", fontsize=12)
        ax.set_ylabel("アドレス数", fontsize=12)
        
    plt.show()

def getPointAttribute(area):
    filename = {"kofu": "/var/www/html/kofu/kofu_position.csv",
                "ff": "/var/www/html/ff/sensor_points.csv",
                "hakushu": "/home/toyoki/public_html/hakushu/points_hakushu.csv",
                "ttri": "/home/toyotamngr/csv/toyota/sensor_points.csv"}
    df = pd.read_csv(filename[area])
    return df.set_index('センサ名').T.to_dict()
In [11]:
# 1か月のデータをカテゴリごとに描画

df1 = pd.read_csv(filename['kofu']).groupby("カテゴリ")
group = []
group.append({"group_name": "中央", "points": df1.get_group("中央")['センサ名'].tolist()})
group.append({"group_name": "丸の内", "points": df1.get_group("丸の内")['センサ名'].tolist()})
group.append({"group_name": "北口・朝日町", "points": df1.get_group("北口・朝日町")['センサ名'].tolist()})
group.append({"group_name": "甲府駅周辺", "points": df1.get_group("甲府駅周辺")['センサ名'].tolist()})

plotDailyDataByGroup(group, "20190801", "20190831","a")
In [24]:
df1 = pd.read_csv(filename['fuefuki']).groupby("グループ")
group = []
group.append({"group_name": "上部", "points": df1.get_group("上部")['センサ名'].tolist()})
group.append({"group_name": "下部", "points": df1.get_group("下部")['センサ名'].tolist()})

plotDailyDataByGroup(group, "20190801", "20190831",addr="a", area="ff", dev="all")
In [ ]: