def __init__(self, fig): # DB 読み込み # DB の読み込み日付の指定. args = cfg['args'] d0 = _d(args.db_begin) df = _d(args.db_end) self.pp2, self.pp3, self.ppj = db_defs(d0, df, args.db_folder) # 評価日時 (10 日毎) self.t0 = sn_fm_dt(d0) self.tf = max(t_max(self.pp2), t_max(self.pp3), t_max(self.ppj)) + 10 self.tt = [a for a in range(int(self.t0), int(self.tf), 10) ] + [int(self.tf)] * 10 # 終端に tf を 10 回繰り返し。 # figure & axis 生成 # self.fig = fig self.ax = fig.add_subplot(1, 1, 1) self.fig.subplots_adjust(left=0) """
def proc_last(pp2, pp3, ppj): """ 作図 支持率 -- 不支持率 最新値(2次元プロット) 最新値と前回からの差分を 支持率--不支持率 グラフ(2次元)にプロットする。 オプションで古い最新値を無視する (-t 14 など)。 オプションでイメージファイル Fig?_yymmdd.png を出力する。 Parameters ---------- pp2, pp3, ppj : グループ毎の DB() リスト. """ args = cfg['args'] xymin, xymax = [int(a) for a in args.xy_range.split(':')] # X軸,Y軸の範囲(X,Y 共通) xoff, yoff = [float(a) for a in args.label_offset.split(':')] # ラベルのオフセット fig = plt.figure(figsize=(4.8 * (1800 / 1012), 4.8)) fig.subplots_adjust(left=0.02, bottom=0.13, right=0.9, top=0.88) ax = fig.add_subplot(1, 1, 1) ax.set_aspect('equal') fig.text( 0.50, 0.847, '線分は前回からの変化', fontsize=10, #fig.text(0.4, 0.14, '各社の最新(線分は前回からの変化)', fontsize=10, bbox=dict(facecolor='gray', edgecolor='none', alpha=0.2)) ax.set_xlabel('内閣を支持する [%]', fontsize=14) ax.set_ylabel('内閣を支持しない [%]', fontsize=14) ax.set_xlim(xymin, xymax) ax.set_ylim(xymin, xymax) ax.set_xticks(range(xymin, xymax + 1, 5)) ax.set_yticks(range(xymin, xymax + 1, 5)) ax.grid(True) # 各社最新 cm = plt.get_cmap('tab10') cn = 0 flg_old = False for (pp, col, ab) in [(ppj, 'brown', 'C'), (pp2, 'indigo', 'グループH'), (pp3, 'green', 'グループL')]: for p in pp: tref = max(t_max(ppj), t_max(pp2), t_max(pp3)) # DB の終端からの日にちで絞る(オプショナル) if args.trimday and (p.db['T'][-1] < (tref - int(args.trimday))): continue if p.db['T'][-1] > tref - 42: alp_mark, alp_line, alp_text = 1.0, 0.8, 0.8 else: alp_mark, alp_line, alp_text = 0.2, 0.2, 0.2 flg_old = True xx = p.db['APP_RATE'][-2:] yy = p.db['NAP_RATE'][-2:] st1 = dt_fm_sn(p.db['T'][-1]).strftime('%m/%d') st2 = dt_fm_sn(p.db['T'][-2]).strftime('%m/%d') s = '%s %s (%s)' % (p.label, st1, st2) ax.plot(xx, yy, '-', lw=1, color=cm(cn), alpha=alp_line) ax.plot(xx[-1], yy[-1], p.marker, ms=p.size, color=cm(cn), alpha=alp_mark, label=s) ax.text(xx[-1] + xoff, yy[-1] + yoff, p.label, fontsize=10, alpha=alp_text) cn = (cn + 1) % 10 ax.plot([0, 100], [0, 100], '--', alpha=0.5) ax.legend(loc='upper left', bbox_to_anchor=(1.02, 1.02)) if flg_old: fig.text(0.7, 0.3, '薄い表示は古い調査(6 週間経過)', fontsize=10) if args.gout: fn = 'Fig%s_%s.png' % (args.gout_ndx, cfg['gout_date']) fig.savefig(os.path.join(args.gout_folder, fn))
def main(): # オプション設定 (cfg['args'] に記録) # opt = options() cfg['args'] = opt.parse_args() args = cfg['args'] # DB 読み込み # DB の読み込み日付の指定. # ma_days [day] 感度解析のウィンドウ(直近 ma_days のデータから感度求める) # args = cfg['args'] d0 = _d(args.db_begin) df = _d(args.db_end) pp2, pp3, ppj = db_defs(d0, df, args.db_folder) ppa = ppj + pp2 + pp3 # ファクター設定 fc_dict = {} for yn in ['APP_RATE', 'NAP_RATE']: fc_dict[yn] = {} tstp = 10 tt = np.arange(t_min(ppa), t_max(ppa), tstp) ff_step = calc_fact(ppa, yn, tt, d_window=6*30) for p, f in zip(ppa, ff_step): fc_dict[yn][p.label] = interp(tt, f) # 補正後の平均 # for k in ['APP_RATE', 'NAP_RATE']: if args.k_days > 0: t0 = sn_fm_dt(d0) t_node = np.arange(t0, t_max(ppa) + 1, 1) # 移動平均を求める時刻 tven_buf[k] = trend_mav(fc_dict, k, t_node, ppa, w_days=30, k_days=args.k_days) else: t0 = sn_fm_dt(d0) t0_sunday = t0 + (6 - d0.weekday()) # 0:月曜 6:日曜 t_node = np.arange(t0_sunday, t_max(ppa) + 3, 7) # 移動平均を求める時刻 tven_buf[k] = trend_sunday(fc_dict, k, t_node, ppa) if 1: proc_trend() proc_trend_x(ppa, fc_dict) if 1: # 公表値/補正値/残差 fig, axes = plt.subplots(3, 2, figsize=(10, 7)) fig.subplots_adjust(left=0.1, bottom=0.1, right=0.90, top=0.95, wspace=0.44) fig.text(0.20, 0.97, '支持する') if args.k_days > 0: fig.text(0.29, 0.62, '平均は指数移動平均') fig.text(0.29, 0.60, '(時定数 %d 日)' % args.k_days) else: fig.text(0.29, 0.62, '平均は日曜前後数日') proc_raw_cal_sdv(fc_dict, axes[:,0], 'APP_RATE', ppa) fig.text(0.70, 0.97, '支持しない') if args.k_days > 0: fig.text(0.75, 0.62, '平均は指数移動平均') fig.text(0.75, 0.60, '(時定数 %d 日)' % args.k_days) else: fig.text(0.75, 0.62, '平均は日曜前後数日') proc_raw_cal_sdv(fc_dict, axes[:,1], 'NAP_RATE', ppa) if args.gout: fig.savefig(os.path.join(args.gout_folder, 'Fig%d_%s.png' % (args.gout_ndx + 2, cfg['gout_date']))) if 1: proc_factor(ppa, 'APP_RATE', '内閣 支持率 感度係数', fc_dict, 3) proc_factor(ppa, 'NAP_RATE', '内閣 不支持率 感度係数', fc_dict, 4) # 表示 # イメージファイルの出力は proc_last() 内で行う # 複数の図を出力するアプリの plot.show() は一つなので main の最後で実施する if args.gout == False: plt.show()
def proc_factor(db_list, k_app_nap, k_title, fc_dict, gn_rel): """ 報道10 社の支持率/不支持率の調査感度の時系列比較 Parameters ---------- db_list, list of DB() k_app_nap, string : 分析データキー ('APP_RATE' or 'NAP_RATE') k_title, string : グラフタイトル fc_dict, - : 他の分析で使っている感度係数補間関数の辞書 gn_rel, : 出力図番の相対 """ args = cfg['args'] # 図の準備 nr = 6 fig, axes = plt.subplots(nr, 2, figsize=(10, 7)) fig.text(0.10, 0.97, k_title, fontsize=16) fig.text(0.60, 0.97, '(オレンジ:3ヵ月移動平均 ブルー:6ヵ月移動平均)', fontsize=12) fig.subplots_adjust(left=0.1, bottom=0.1, right=0.95, top=0.95, wspace=0.25, hspace=0.25) # 分析期間 t0 = sn_fm_dt(_d(cfg['args'].db_begin)) tf = t_max(db_list) # 移動平均の窓幅をいくつか選んで感度のトレンドを描画(調査会社毎) for ndx, m in enumerate([3, 6]): # window size (m-month) tt = np.arange(t0 + 6*30, tf, 7) ff = calc_fact(db_list, k_app_nap, tt, m*30) dd = [dt_fm_sn(a) for a in tt] for j, (f, db) in enumerate(zip(ff, db_list)): c, r = divmod(j, nr) if ndx == 0: axes[r,c].plot(dd, f, color='orange', lw=2, alpha=0.8) else: axes[r,c].plot(dd, f, color='blue') fc = [fc_dict[k_app_nap][db.label](t) for t in tt] axes[r,c].plot(dd, fc, '-', color='green', alpha=0.5) axes[r,c].set_xlim(dd[0], dd[-1]+timedelta(days=30)) # タイトルや軸の設定 db_list_ax = db_list + ['']*(nr*2 - len(db_list)) print('db_list_ax', len(db_list_ax)) for j, db in enumerate(db_list_ax): c, r = divmod(j, nr) axes[r,c].set_xlim(dd[0], dd[-1]+timedelta(days=30)) if db != '': axes[r, c].set_ylabel(db.label) axes[r, c].set_ylim(0.8, 1.3) axes[r, c].grid(which='both') axes[r, c].grid(which='minor', alpha=0.1) if r == (nr - 1): print(r, c) set_date_tick(axes[r,c], (1, 7), '%Y/%m', 30) else: set_date_tick(axes[r,c], (1, 7), '%m', 0) # 調査が実施された日付をプロット if db != '': dd_org = [dt_fm_sn(a) for a in db.db['T']] oo_org = np.ones_like(dd_org) axes[r,c].plot(dd_org, oo_org, 'o', ms=4, alpha=0.2) if args.gout: fig.savefig(os.path.join(args.gout_folder, 'Fig%d_%s.png' % (args.gout_ndx + gn_rel, cfg['gout_date'])))
def main(): # オプション設定 (cfg['args'] に記録) # opt = options() cfg['args'] = opt.parse_args() args = cfg['args'] # DB 読み込み # DB の読み込み日付の指定. # ma_days [day] 感度解析のウィンドウ(直近 ma_days のデータから感度求める) # args = cfg['args'] d0 = _d(args.db_begin) df = _d(args.db_end) pp2, pp3, ppj = db_defs(d0, df, args.db_folder) # ファクター設定 fc_dict = {} for yn in ['APP_RATE', 'NAP_RATE']: fc_dict[yn] = {} for db_list in [ppj, pp2, pp3]: tstp = 10 tt = np.arange(t_min(db_list), t_max(db_list), tstp) ff_step = calc_fact(db_list, yn, tt, d_window=6 * 30) for db, f in zip(db_list, ff_step): fc_dict[yn][db.label] = interp(tt, f) # 補正後の平均 # t0 = sn_fm_dt(d0) t_node2 = np.arange(t0, t_max(pp2) + 1, 1) t_node3 = np.arange(t0, t_max(pp3) + 1, 1) t_nodej = np.arange(t0, t_max(ppj) + 1, 1) for k in ['APP_RATE', 'NAP_RATE']: if args.k_days > 0: tven_buf['H'][k] = trend_mav(fc_dict, k, t_node2, pp2, w_days=30, k_days=args.k_days) else: t0 = sn_fm_dt(d0) t0_sunday = t0 + (6 - d0.weekday()) # 0:月曜 6:日曜 t_node = np.arange(t0_sunday, t_max(pp2) + 3, 7) # 移動平均を求める時刻 tven_buf['H'][k] = trend_sunday(fc_dict, k, t_node, pp2) for k in ['APP_RATE', 'NAP_RATE']: if args.k_days > 0: tven_buf['L'][k] = trend_mav(fc_dict, k, t_node3, pp3, w_days=30, k_days=args.k_days) else: t0 = sn_fm_dt(d0) t0_sunday = t0 + (6 - d0.weekday()) # 0:月曜 6:日曜 t_node = np.arange(t0_sunday, t_max(pp3) + 3, 7) # 移動平均を求める時刻 tven_buf['L'][k] = trend_sunday(fc_dict, k, t_node, pp3) for k in ['APP_RATE', 'NAP_RATE']: if args.k_days > 0: tven_buf['J'][k] = trend_mav(fc_dict, k, t_nodej, ppj, w_days=30, k_days=args.k_days) else: t0 = sn_fm_dt(d0) t0_sunday = t0 + (6 - d0.weekday()) # 0:月曜 6:日曜 t_node = np.arange(t0_sunday, t_max(ppj) + 3, 7) # 移動平均を求める時刻 tven_buf['J'][k] = trend_sunday(fc_dict, k, t_node, ppj) if 1: proc_trend() if 1: # 公表値/補正値/残差 for yn in ['APP_RATE', 'NAP_RATE']: fig, axes = plt.subplots(3, 2, figsize=(10, 7)) fig.subplots_adjust(left=0.1, bottom=0.1, right=0.90, top=0.95, wspace=0.44) fig.text(0.15, 0.97, '支持%s(グループH)' % { 'APP_RATE': 'する', 'NAP_RATE': 'しない' }[yn]) if args.k_days > 0: fig.text(0.29, 0.62, '平均は指数移動平均') fig.text(0.29, 0.60, '(時定数 %d 日)' % args.k_days) else: fig.text(0.29, 0.62, '平均は日曜前後数日') tt2, avg, err, num = tven_buf['H'][yn].by_column() proc_raw_cal_sdv(fc_dict, axes[:, 0], yn, pp2, tt2, avg) fig.text(0.65, 0.97, '支持%s(グループL)' % { 'APP_RATE': 'する', 'NAP_RATE': 'しない' }[yn]) if args.k_days > 0: fig.text(0.75, 0.62, '平均は指数移動平均') fig.text(0.75, 0.60, '(時定数 %d 日)' % args.k_days) else: fig.text(0.75, 0.62, '平均は日曜前後数日') tt3, avg, err, num = tven_buf['L'][yn].by_column() proc_raw_cal_sdv(fc_dict, axes[:, 1], yn, pp3, tt3, avg) if args.gout: if yn == 'APP_RATE': fig.savefig( os.path.join( args.gout_folder, 'Fig%d_%s.png' % (args.gout_ndx + 2, cfg['gout_date']))) else: fig.savefig( os.path.join( args.gout_folder, 'Fig%d_%s.png' % (args.gout_ndx + 3, cfg['gout_date']))) if 1: proc_yn(pp2, pp3, ppj) if 1: proc_fc(fc_dict, pp2, pp3, ppj) if 1: proc_hilo() # 表示 # イメージファイルの出力は proc_last() 内で行う # 複数の図を出力するアプリの plot.show() は一つなので main の最後で実施する if args.gout == False: plt.show()