風が強いテニスコートはどこだ! 過去10年間のインターハイ決勝会場比較
Tellusに搭載されている分刻みの風速データを用いて、過去10年間のうちに硬式テニスのインターハイ決勝が行われた会場を比較してみました。
錦織圭選手、大阪なおみ選手、国枝慎吾選手……2020五輪の国内注目選手が集まる種目として、硬式テニスはそのひとつに入るといっても過言ではないでしょう。
競技が行われるのは有明テニスの森公園という会場のようなのですが、いったいどのようなテニスコートなのでしょうか。
今回はテニスのプレイに影響を与えるひとつの要素「風の強さ」に焦点を当て、衛星データプラットフォーム「Tellus」に搭載されているデータを用いて、2009年から2019年の間にインターハイ(硬式テニス)が行われた会場と比較してみました。
1.調査するテニスコートと調査方法
まず、今回の調査対象となったテニスコートは以下。
そして、Tellus上にもプロットしてみました。
過去11年間の会場を調べてみるとどうやらテニスコートは12の会場が利用されたようです。2020年の東京五輪が行われる有明テニスの森公園も入っていますね。
では、どのように風速を比較するかについて、今回は以下の要件で風速を比較してみました。
★★★
データの取得方法:Tellus APIのアメダスデータ
期間:2017年7月25日~2017年8月2日
取得するデータ:上記期間の9時から17時までの、各時刻の平均風速を算出
地点:テニスコート最寄りの風速計がある地点
比較方法:最小値、最大値、平均値、中央値の4つの比較を実施
★★★
それではさっそく結果を見てみましょう。
2.結果発表
TellusのAPIを用いてデータを抽出した結果、以下のようになりました。最小値、最大値、平均値、中央値の4つについて、並べています。
※グラフ画像、会場の表記順序は中央値の昇順
実数は以下になります。
データを見ると、東京五輪会場(有明テニスの森公園)は中央値で見ると中間ですが、最大値は他会場と比較してもっとも大きく、最小値も3位という結果に。テニスプレイヤーにとっては、風が強い会場と言えるでしょう。
また、結果だけ見ると青森会場と沖縄会場はどの値をとっても風が強くいようで、風が苦手なテニスプレイヤーにとってはプレイしづらい会場なのかもしれません。
逆に、三重県の四日市ドーム、新潟の大原運動公園は風が弱く、伸び伸びとテニスを楽しめそうですね。
※台風の時期ということもあり、データをより正確に検証するためには、外れ値を除外したり、もっと多くのデータを取得する必要がありますが、今回は簡単な比較のみでとどめております。
3.Tellus APIを用いたデータの抽出方法
では、本データをどのようにして取得するのか。今回の作業を大きくまとめると以下3つの工程になります。
①Tellus APIを叩く準備
②取得したい場所とデータを指定してAPIを叩く
③抽出したデータの保存
これから、3つの工程を一つずつ解説します。
※TellusでJupyter Lab(Jupyter Notebook)を使う方法は、「Tellusの開発環境でAPI引っ張ってみた」をご覧ください。
①Tellus APIを叩く準備
まずはTellusのAPIを叩くための準備が必要になります。
今回は毎分のデータを1時間ごとに平均して取得します。その設定の他にも、また、無効の値や信頼性の低いデータを判別して除外する、観測データから指定の観測値データを取り出すなど、あらかじめ準備が必要なのです。
これをまとめたサンプルコードが以下になります。
import requests, json
from datetime import datetime
from datetime import timedelta
from dateutil.relativedelta import relativedelta
import numpy as np
TOKEN = 'ここには自分のアカウントのトークンを貼り付ける'
def get_amedas_1min(year, month, day, hour, minute, payload={}):
"""
/api/v1/amedas/1minを叩く
Parameters
----------
year : string
西暦年 (4桁の数字で指定) UTC
month : string
月 01~12 (2桁の数字で指定) UTC
day : string
日 01~31 (2桁の数字で指定) UTC
hour : string
時 00~23 (2桁の数字で指定) UTC
minute : dict
分 00~59 (2桁の数字で指定) UTC
payload : dict
パラメータ(min_lat,min_lon,max_lat,max_lon)
Returns
-------
content : list
結果
"""
url = 'https://gisapi.tellusxdp.com/api/v1/amedas/1min/{}/{}/{}/{}/{}/'.format(year, month, day, hour, minute)
headers = {
'Authorization': 'Bearer ' + TOKEN
}
r = requests.get(url, headers=headers, params=payload)
if not r.status_code == requests.codes.ok:
r.raise_for_status()
return json.loads(r.content)
def get_hourly_data(target_datetime, station_ids, data_type, data_name, flag_name=None, max_flag=11, payload={}, hour=1):
"""
1時間毎のデータを取得(平均値)
Parameters
----------
datetime : datetime.datetime
取得する日時(日本標準時)
station_ids : list of int
取得する観測所のidの配列
data_type : string
観測データ種別
data_name : string
データ名
flag_name : string
フラグ名
max_flag : int
正常フラグ上限
payload : dict
パラメータ(min_lat,min_lon,max_lat,max_lon)
hour : int
取得時間幅
Returns
-------
content : dict
結果
"""
def is_valid(value_obj, flag_obj={}, max_flag=11):
"""
無効値や信頼性の低い観測データを判別
"""
byte_size = {
1: 127,
2: 32767,
4: 2147483647
}
return (flag_obj == {} or flag_obj['value'] <= max_flag) and value_obj['value'] != byte_size[value_obj['size']]
data_dict = {}
for id in station_ids:
data_dict[id] = []
def get_hourly(target_datetime):
begin_datetime = datetime(target_datetime.year, target_datetime.month, target_datetime.day, target_datetime.hour, 0, 0, 0)
end_datetime = begin_datetime + timedelta(hours=1)
temp_datetime = begin_datetime
while temp_datetime 0:
result[station_id] = np.mean(np.array(data_dict[station_id])/10)
else:
result[station_id] = 0.0
return result
begin_datetime = datetime(target_datetime.year, target_datetime.month, target_datetime.day, target_datetime.hour, 0, 0, 0)
end_datetime = begin_datetime + timedelta(hours=hour)
temp_datetime = begin_datetime
result = {}
while temp_datetime < end_datetime:
result[temp_datetime.hour] = get_hourly(temp_datetime)
temp_datetime += timedelta(hours=1)
return result
②取得したい場所とデータを指定してAPIを叩く
次に、取得したい場所とデータの指定です。
今回はアメダスのデータを用いるため、アメダスが管理する風速計のある場所のデータを指定する必要があります。テニスコートの地点にちょうど風速計があれば良いのですが、そんな都合の良いことはありませんでした。
そのため、アメダスの地図データから、テニスコート最寄りの風速計がある場所を探して指定しました。
次に、取得するデータの指定です。詳細はTellusのAPIリファレンスになりますが、今回は風速を取得するため”wind”を指定します。
その他、取得する開始時間と、何時まで取得するのかなど、これをまとめたサンプルコードが以下になります。
# ここに会場最寄りのアメダス観測所IDを入れる
ids = [64036, 91197, 31312, 54841, 54616, 54501, 82186, 44136, 62078, 68132, 36361, 53061, 87412, 45261]
begin_hour = 9 # 取得開始時刻
duration_hour = 9 # 取得範囲(時間)
begin_datetime = datetime(2017,7,25) # 取得開始日
end_datetime = begin_datetime + timedelta(days=8) # 取得終了日
temp_datetime = begin_datetime
data_type ='wind' # 取得するデータ種別
data_name = 'velocity_ave' # 取得するデータ名
flag_name = 'velocity_ave_flag' # 取得するデータの正常フラグ名
result = {}
while temp_datetime <= end_datetime:
print('search now {0:%Y-%m-%d}'.format(temp_datetime))
result['{0:%Y-%m-%d}'.format(temp_datetime)] = get_hourly_data(datetime(temp_datetime.year,temp_datetime.month,temp_datetime.day,begin_hour), ids, data_type, data_name, flag_name, payload={
'min_lat': -90,
'min_lon': -180,
'max_lat': 90,
'max_lon': 180
}, hour=duration_hour)
temp_datetime += timedelta(days=1)
print('complete!')
③抽出したデータの保存
最後に、以下のサンプルコードが抽出したデータを保存するためのものになります。
import csv
print('start!')
for id in ids:
with open('amedas_{}.csv'.format(id), 'w') as f:
writer = csv.writer(f, lineterminator='\n')
writer.writerow(['id'] + list(range(begin_hour, begin_hour + duration_hour)))
for day in result.keys():
row = [day]
for hour in range(begin_hour, begin_hour + duration_hour):
row.append(result[day][hour][id])
writer.writerow(row)
print('saved {}'.format(id))
print('end.')
以上、3つのサンプルコードを用いて今回のテニスコートの比較を行いました。ぜひ気になる場所があれば試してみてください。
4.まとめと今後チャレンジしたいこと
今回は風速のみの比較でしたが、雨がよく振るか否か(365日中雨だった日は何日か)、湿度、日照時間、気温など、テニスプレイヤーにとって気になる項目を抽出すれば、各テニスコートのレーダーチャートも作れるかもしれません。
そして、テニスコートだけではなく、気象が影響する様々なスポーツ・イベントの会場比較もきっと面白いでしょう。
フェス、お祭り、花火、野球、サッカー、競馬……などなど。
今回の記事をきっかけに様々な場所の比較データが誰にでも見える形で可視化されることを楽しみにしています。