名古屋人with me?ツアーで最も日帰りが容易だった説

この記事はゆかりっく Advent Calendar 2023 20日目の記事です。

昨日(12月19日)は、餅子まるさんによる「"パブリックゆかりん"は変化する?について考えてみた。」でした。

パブリックゆかりんとライブで魅せるゆかりんとのギャップいいですよね、年月が経ちパブリックゆかりんがどう変化していくか楽しみです。



はじめに

はじめまして、じゃむ(@yukarinji_227)と申します。
ゆかりっくアドベントカレンダーに参加するのは初めてですが、どうかお手柔らかにお願いいたします。

初参戦は2013年のCaramel Ribbonファンクラブ9年目のおじさんです。
比較的重めのゆかりんが好きです。ライブだとSsLとか
最新EPのAltoemionも重めで落ち着ける感じの曲が多くて良かったです。
今年のツアーは13公演参加しました。

さて、ゆかりんを追って全国を飛び回る系おじさんが
一度は考えたことがあるであろう疑問それは

「どこの都市に住むのが一番楽にツアー参戦できるのだろうか」

この記事ではその疑問を今年のwith me?ツアーのデータを元に検証していきたいと思います。
楽といってもいろんな定義があると思います。時間、費用、手間…等々
費用は移動手段や予約時期によって大きく異なりますし、
ここでは、時間、特に日帰りで帰宅ができるかどうかという点に絞って検証していきます。

以下の記事は12/19時点の内容です。今後加筆修正されることがあります。
記事の内容に基づいての行動に関して、当方は一切の責任を負いかねます。

仮説

以前から思っていたんです。ゆかりんのツアーは大体全国をまんべんなく回るので、私が住んでいる名古屋圏が一番日帰りで参戦できるのではないかと
また、とある打ち上げのバスで隣になった方が同じ県に住む方でかつ全通している方だったのですが、その方曰く○○以外は大体日帰りで帰ってこれたと行っていたのです。

それでは説立証目指して検証していきます!

検証ルール

  • 当日中に東京駅、新大阪駅、名古屋駅、博多駅到着できたらOKとする

  • 利用する交通機関は、飛行機、鉄道、路線バス、のみとし高速バス、タクシーは利用しない

  • 公演名は感想ハッシュタグの地名部分に準拠する

  • 出発時刻は各公演終了後20分とし埼玉、神奈川、千秋楽公演以外では午後8時20分をベースとする

  • 倉敷公演は予定通り行われたものとする



検証手法

1公演ずつ経路検索をして当日中に帰れたか判定してExcelにまとめようかと思ったのですが28公演×4駅となると112回経路検索をしないとなりません。とてもじゃないけど、そんな手間はかけられません…困ったな

困ったときのChatGPTというわけで、とりあえず聞いてみた結果がこちら

どうやらAPIってのを使ってPythonでプログラミングすればいいようです。
しかし僕自身がコードを書くような仕事でもなくプログラミング知識が全くと言っていいほど無いため、このままChatGPTに任せてコードを書いてもらうことにしました。
ちなみこの検証12/5スタートです。


ChatGPTと対話を続けること数日できあがったのが以下のコード
APIはRapid APIで公開されているNAVITIME Route(totalnavi)を使用しました。

import pandas as pd
import requests
from datetime import datetime

# APIキー
api_key = ""

# エンドポイント
endpoint = "https://navitime-route-totalnavi.p.rapidapi.com/route"

# Excelファイルのパス
excel_path = 'C:/yukari/withme.xlsx'

# ヘッダー
headers = {
    'X-RapidAPI-Host': 'navitime-route-totalnavi.p.rapidapi.com',
    'X-RapidAPI-Key': 'sekai1kawaiiyo!'
}

# Excelファイル読み込み
df = pd.read_excel(excel_path)

# データの取得と処理
for index, row in df.iterrows():
    # 出発地
    start_latitude, start_longitude = row['出発場所_緯度'], row['出発場所_経度']
    
    # 到着地
    goal_latitude, goal_longitude = row['到着駅_緯度'], row['到着駅_経度']
    
    # 出発時間のフォーマット
    departure_time = datetime.fromisoformat(row['出発時間'])

    # パラメーター
    params = {
        'start': f"{start_latitude},{start_longitude}",
        'goal': f"{goal_latitude},{goal_longitude}",
        'start_time': departure_time.isoformat(),
        'datum': 'wgs84',
        'term': 1440,
        'limit': 5,
        'coord_unit': 'degree'
    }

    # APIリクエスト
    response = requests.get(endpoint, headers=headers, params=params)

    # 正常なレスポンスか確認
    if response.status_code == 200:
        data = response.json()

        # 到着時間があるかどうかを確認
        if 'items' in data and data['items']:
            to_time = datetime.fromisoformat(data['items'][0]['summary']['start']['move'][0]['to_time'][:-6])

            # 当日の26時までかどうかを判定
            if to_time.hour < 26:
                df.at[index, 'to_time'] = to_time
                df.at[index, 'E列'] = '○'
            else:
                df.at[index, 'to_time'] = to_time
                df.at[index, 'E列'] = '×'
        else:
            df.at[index, 'to_time'] = pd.NaT  # NaNとして扱う
            df.at[index, 'E列'] = 'データなし'
    else:
        print(response.json())  # エラーの詳細を表示
        df.at[index, 'to_time'] = pd.NaT  # NaNとして扱う
        df.at[index, 'E列'] = f'エラー: {response.status_code}'

# Excelに書き込み
df.to_excel(excel_path, index=False)

結局これでは動かず分かる人に教えてもらったり、手直ししてもらい到着時刻を出力できるようになったのが以下のコード

# coding: utf-8
import pandas as pd
import requests

import json
#from pandas.io.json import json_normalize
from datetime import datetime

# APIキー
api_key = "sekai1kawaiiyo!"

# エンドポイント
endpoint = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit"
#endpoint = "https://navitime-route-totalnavi.p.rapidapi.com/route"

# Excelファイルのパス
excel_path = 'C:\yukari\withme.xlsx'

# ヘッダー
headers = {
    'X-RapidAPI-Host': 'navitime-route-totalnavi.p.rapidapi.com',
    'X-RapidAPI-Key': 'sekai1kawaiiyo!'
}

# Excelファイル読み込み
df = pd.read_excel(excel_path)

# データの取得と処理
for index, row in df.iterrows():
    # 出発地
    start_latitude, start_longitude = row['出発場所_緯度'], row['出発場所_経度']
    
    # 到着地
    goal_latitude, goal_longitude = row['到着駅_緯度'], row['到着駅_経度']
    
    # 出発時間のフォーマット
    #ここ文字列型で送信する 2023-04-22T19:45:00
    departure_time = row['出発時間']

    # パラメーター
    params = {
        'start': f"{start_latitude},{start_longitude}",
        'goal': f"{goal_latitude},{goal_longitude}",
        #'start_time': departure_time.isoformat(),
        'start_time': str(departure_time),
        'datum': 'wgs84',
        'term': 1440,
        'limit': 5,
        'coord_unit': 'degree'
    }

    print(str(start_latitude) +','+ str(start_longitude))
    print(str(goal_latitude) +','+ str(goal_longitude))
    print(departure_time)
    #print(departure_time.isoformat())

    # APIリクエスト
    response = requests.get(endpoint, headers=headers, params=params)

    # 正常なレスポンスか確認
    if response.status_code == 200:
        data = response.json()

        print(data['items'][0]['summary']['move']['to_time'])
        #中身はこれになる。

        print(response.status_code)
        # 到着時間があるかどうかを確認
        if 'items' in data and data['items']:
            #to_time = datetime.fromisoformat(data['items'][0]['summary']['start']['move'][0]['to_time'][:-6])
            #to_time = data['items'][0]['summary']['start']['move'][0]['to_time'][:-6]
            
            to_time=datetime.fromisoformat(data['items'][0]['summary']['move']['to_time'])
            
            # 当日の26時までかどうかを判定
            if to_time.hour < 26:
                df.at[index, 'to_time'] = data['items'][0]['summary']['move']['to_time'] #直接文字をそのまま出すことにした
                df.at[index, 'E列'] = '○'
            else:
                df.at[index, 'to_time'] = data['items'][0]['summary']['move']['to_time'] #直接文字をそのまま出すことにした
                df.at[index, 'E列'] = '×'
        else:
            df.at[index, 'to_time'] = None  # NaNとして扱う_なしならNONEでOKでは
            df.at[index, 'E列'] = 'データなし'
    else:
        print(response.json())  # エラーの詳細を表示
        df.at[index, 'to_time'] = None  # NaNとして扱う
        df.at[index, 'E列'] = f'エラー: {response.status_code}'

# Excelに書き込み
df.to_excel(excel_path, index=False)


修正してもらったコードを元にさらにChatGPTとの対話をつづけ
当日判定などを修正してできたのがこちらのコード。

# coding: utf-8
import pandas as pd
import requests
import openpyxl

import json
#from pandas.io.json import json_normalize
from datetime import datetime, timezone, timedelta

'''
#Excel強制終了(公開時はコメントアウトすること)
import psutil
import os

def kill_excel_processes():
    for proc in psutil.process_iter(['pid', 'name']):
        try:
            # Excelプロセスを検出
            if 'EXCEL.EXE' in proc.info['name']:
                print(f"Killing Excel process with PID {proc.info['pid']}")
                # プロセスを終了する
                psutil.Process(proc.info['pid']).terminate()
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass

if __name__ == "__main__":
    try:
        # Excelプロセスを強制終了
        kill_excel_processes()
    except Exception as e:
        print(f"Error: {e}")
    finally:
        # 念のため残っているExcelプロセスがあれば終了
        os.system("taskkill /f /im EXCEL.EXE")

'''
    
# APIキー
api_key = "sekai1kawaiiyo!"

# エンドポイント
endpoint = "https://navitime-route-totalnavi.p.rapidapi.com/route_transit"
#endpoint = "https://navitime-route-totalnavi.p.rapidapi.com/route"

# Excelファイルのパス
excel_path = "C:\\yukari\\withme_data.xlsx"


# ヘッダー
headers = {
    'X-RapidAPI-Host': 'navitime-route-totalnavi.p.rapidapi.com',
    'X-RapidAPI-Key': 'sekai1kawaiiyo!'
}

# Excelファイル読み込み
df = pd.read_excel(excel_path)


# データの取得と処理
for index, row in df.iterrows():
    # 出発地
    start_location = row['出発駅_緯度経度']
    if isinstance(start_location, str):
        start_latitude, start_longitude = map(float, start_location.split(','))
    else:
        start_latitude, start_longitude = float(start_location), float(row['出発駅_緯度経度'])

    # 到着地
    goal_location = row['到着駅_緯度経度']
    if isinstance(goal_location, str):
        goal_latitude, goal_longitude = map(float, goal_location.split(','))
    else:
        goal_latitude, goal_longitude = float(goal_location), float(row['到着駅_緯度経度'])
        
    # 出発時間のフォーマット
    departure_time_str = row['駅出発時間']

    # パラメーター
    params = {
        'start': f"{start_latitude},{start_longitude}",
        'goal': f"{goal_latitude},{goal_longitude}",
        'start_time': str(departure_time_str),
        'datum': 'wgs84',
        'term': 1440,
        'limit': 1,
        'train_data': 'average',
        #'train_data': 'timetable',
        'unuse': 'domestic_flight',
        'coord_unit': 'degree'
    }

    # APIリクエスト
    response = requests.get(endpoint, headers=headers, params=params)

    # 正常なレスポンスか確認
    if response.status_code == 200:
        data = response.json()

        print(data['items'][0]['summary']['move']['to_time'])
        print(response.status_code)

        # 到着時間があるかどうかを確認
        if 'items' in data and data['items']:
            to_time_str = data['items'][0]['summary']['move']['to_time']

            # to_time_strが文字列であることを確認してから変換
            if isinstance(to_time_str, str):
                # タイムゾーン情報を考慮したdatetimeオブジェクトに変換
                to_time = datetime.fromisoformat(to_time_str)

                # 出発時間をUTCに変換
                departure_time_utc = datetime.fromisoformat(departure_time_str)

                # UTCでの到着時間と出発時間の日付を比較
                if to_time.replace(tzinfo=None).date() == departure_time_utc.replace(tzinfo=None).date():
                    df.at[index, '判定'] = '♡'
                else:
                    df.at[index, '判定'] = '×'

                df.at[index, '到着時間'] = to_time_str
            else:
                df.at[index, '到着時間'] = None
                df.at[index, '判定'] = 'データなし'
        else:
            df.at[index, '到着時間'] = None
            df.at[index, '判定'] = 'データなし'
    else:
        print(response.json())
        df.at[index, '到着時間'] = None
        df.at[index, '判定'] = f'エラー: {response.status_code}'

# Excelに書き込み
df.to_excel(excel_path, index=False)


# Excelファイルのパス
file_path = r'C:\yukari\withme_data.xlsx'

try:
    # Excelアプリケーションを開く
    subprocess.Popen(['start', 'excel', file_path], shell=True)

except Exception as e:
    print(f"エラーが発生しました: {e}")

あとは実行あるのみです。
ただ出発時間と出発地、到着地の座標入力は、人力でExcelファイルに書き込んでいかなければなりません。結局かなりアナログ…

出力内容

このコードを実行すると到着時間と判定がこのようにExcelファイルに追加されます。

これが28公演分出力されます。


以下の表は判定結果をまとめたものです。

東京の勝利ですが名古屋も健闘してますね

でこれ正確なの?

いいえ、全くもって正確ではありません。

なぜなら、Rapid APIで公開されているAPIでは、時刻表データを使えず平均所要時間を用いた乗換検索検索しかできないためです。
そのため新潟発福岡が翌日の午前4時50分着とか平気で出してきます。
飛行機の利用をありにすると深夜でも平気で離発着します。

このことに全てのデータを出力してから気づきました。
今日のことです…

でどうするのこれ?

  • 時刻表データを用いた乗換検索をできるAPIをどうにかして用意し再実行する

  • 判定が♡でも到着時間が終電時間付近など怪しい所は人力で再検証し最終判定を行う。

結果発表

は上記のどちらかを実施し年内に追記します。
最悪全部人力でやり直します()

気が付いたら1/2ですね、みなさまあけましておめでとうございます。
結果は2/27までにやります。たぶん人力で…

まとめ

  • プログラミングの知識が全くない人でもChatGPTに条件を投げるだけでコードらしき物が返ってくるのは便利であると共に怖さを感じた。

  • 以前に比べて駅に近い会場での開催が増えたように感じ姫の優しさを感じた。

  • 終演時間を調べるときにハッシュタグ付きで参加した公演の終演時間をツイートしてる人がいて助かった。

  • これだけ日数と手間がかかるなら全部手作業でまとめた方が楽で早かったのでは

  • Google Map Directions APIが日本国内でも経路検索に対応していればこうはならなかったはず。

  • 来年こそはちゃんと勉強しようと思う、そのきっかけになったので意味ある検証だったと思う。

さいごに

来年はどこの都市でライブをするのだろうかと思っていたら、来年のライブ予定が発表されましたね。
関東圏での開催が多く来年はこのような検証の必要がなくなり胸をなで下ろしております。
長文かつ乱文でしたが、最後までお付き合いいただきありがとうございます。

それでは、また来年全国各地でお会いしましょう!

明日は、壱音さんの「私の好きなホールのお話」です。
色々な会場で公演してきたゆかりんですが一体どこのホールのお話なんでしょうか?
僕は、大阪のフェスティバルホールが一番好きです。
またあの音響でゆかりんの楽曲を聴いてみたいものです。











この記事が気に入ったらサポートをしてみませんか?