Skip to content

Instantly share code, notes, and snippets.

@yano404
Last active June 17, 2023 20:07
Show Gist options
  • Save yano404/ece205af2e7e2c0ec15e to your computer and use it in GitHub Desktop.
Save yano404/ece205af2e7e2c0ec15e to your computer and use it in GitHub Desktop.
気象庁のホームページから世界103地点の気象データを入手して、気候区分を判定するプログラム
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__version__ = '0.0.1'
## import required libraries
import pandas
from decimal import Decimal
import numpy as np
## CONSTANT
PROGRAM_DESCRIPTION = '''
###############################################################################
ケッペンの気候区分判定プログラム
作者: KouQ7802
ライセンス: GPLv3
''' + 'バージョン: ' + __version__ + '''
###############################################################################
'''
REGION = {0:'東アジア・シベリア',
1:'南アジア',
2:'ヨーロッパ',
3:'中東・アフリカ',
4:'北アメリカ',
5:'南アメリカ',
6:'オセアニア',
7:'南極'}
KOPPEN_CLIMATIC_DIVISION_LIST = {'Af':'熱帯雨林気候',
'Am':'熱帯雨林気候(弱い乾季あり)',
'Aw':'サバナ気候',
'BS':'ステップ気候',
'BW':'砂漠気候',
'Cfa':'温暖湿潤気候',
'Cfb':'西岸海洋性気候',
'Cs':'地中海性気候',
'Cw':'温暖冬季少雨気候',
'Df':'亜寒帯湿潤気候',
'Dw':'亜寒帯冬季少雨気候',
'ET':'ツンドラ気候',
'EF':'氷雪気候'}
## preprocess
# fetch climatic data from server of Japan Meteorological Agency
# 気象庁のWebページより世界の主要な地点の月別の気温・降水量平年値のデータを得る
CLIMATIC_DATA_SOURCE = 'http://www.data.jma.go.jp/gmd/cpd/monitor/mainstn/nrmlist.php'
RAW_CLIMATIC_DATA = pandas.io.html.read_html(CLIMATIC_DATA_SOURCE)
# rearrange CLIMATIC_DATA
# CLIMATIC_DATAを整理する
for i in range(len(RAW_CLIMATIC_DATA)):
for j in range(2, len(RAW_CLIMATIC_DATA[i]), 2):
for k in range(12, -1, -1):
RAW_CLIMATIC_DATA[i].xs(j)[k+2] = RAW_CLIMATIC_DATA[i].xs(j)[k]
RAW_CLIMATIC_DATA[i].xs(j)[0] = np.nan
RAW_CLIMATIC_DATA[i].xs(j)[1] = np.nan
## define functions
def show_region():
for i in range(len(REGION)):
print(i, ':', REGION[i])
print(len(REGION), ':', '全地域')
def show_city(region_key):
if region_key == len(REGION):
for i in range(len(RAW_CLIMATIC_DATA)):
for j in range(1, len(RAW_CLIMATIC_DATA[i]), 2):
print(i, REGION[i], ':', RAW_CLIMATIC_DATA[i][0][j])
print('===============================================================================')
else:
for i in range(1, len(RAW_CLIMATIC_DATA[region_key]), 2):
print(i, ':', RAW_CLIMATIC_DATA[region_key][0][i])
def search_index(city_name):
for i in range(len(RAW_CLIMATIC_DATA)):
for j in range(1, len(RAW_CLIMATIC_DATA[i]), 2):
if city_name in RAW_CLIMATIC_DATA[i][0][j]:
city_index = (i, j)
break
return city_index
def get_city_index():
while True:
show_region()
while True:
print('判定対象の都市がある地域の番号を入力してください')
try:
region_key = int(input('-->'))
break
except ValueError:
continue
if region_key<0 or 8<region_key:
continue
show_city(region_key)
if region_key == 8:
continue
print('判定対象の都市は見つかりましたか?(Y/n)')
switch = input('-->')
if switch == 'Y' or switch == 'y':
break
else:
continue
while True:
print('都市名または都市の番号を入力してください')
city_name = input('-->')
try:
if isinstance(int(city_name), int):
if int(city_name) % 2 == 1:
city_index = (region_key, int(city_name))
break
else:
pass
except ValueError:
pass
if isinstance(city_name, str):
try:
city_index = search_index(city_name)
break
except UnboundLocalError:
print('入力された都市は見つかりませんでした')
continue
else:
continue
return city_index
def show_target_city(city_index):
print('都市名: ', RAW_CLIMATIC_DATA[city_index[0]][0][city_index[1]])
print('国名または地域名: ', RAW_CLIMATIC_DATA[city_index[0]][1][city_index[1]])
print('太州名: ', REGION[city_index[0]])
# generate climatic data(pandas.DataFrame)
def gen_pandas_dataframe(city_index):
city_climatic_data = pandas.DataFrame()
city_temperature = pandas.DataFrame()
city_precipitation = pandas.DataFrame()
for i in range(3,15):
city_temperature = \
city_temperature.append( [Decimal(RAW_CLIMATIC_DATA[city_index[0]].xs(city_index[1])[i])] )
if RAW_CLIMATIC_DATA[city_index[0]].xs(city_index[1]+1)[i] == '---':
city_precipitation = city_precipitation.append([np.nan])
else:
city_precipitation = \
city_precipitation.append( [Decimal(RAW_CLIMATIC_DATA[city_index[0]].xs(city_index[1]+1)[i])] )
city_temperature = city_temperature.append([city_temperature.mean()])
city_precipitation = city_precipitation.append([city_precipitation.sum()])
city_climatic_data = pandas.concat([city_temperature, city_precipitation], axis=1)
city_climatic_data.index = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'annual']
city_climatic_data.columns = ['temperature', 'precipitation']
return city_climatic_data
# judge North Hemisphere or South Hemisphere
def judge_north_south(city_climatic_data):
temperature_high_to_low = city_climatic_data[:12].sort('temperature', ascending=False)
if 4 <= temperature_high_to_low.index[0] <= 9:
north_south = True
else:
north_south = False
return north_south
# judge climatic region of target city
def judge_fsw(city_climatic_data):
max_precipitation = city_climatic_data['precipitation'][:12].max()
min_precipitation = city_climatic_data['precipitation'][:12].min()
precipitation_high_to_low = city_climatic_data[:12].sort('precipitation', ascending=False)
if judge_north_south(city_climatic_data):
if 4<= precipitation_high_to_low.index[11] <= 9:
if min_precipitation*3 <= max_precipitation:
climatic_region = 's'
else:
climatic_region = 'f'
else:
if min_precipitation*10 <= max_precipitation:
climatic_region = 'w'
else:
climatic_region = 'f'
else:
if 4<= precipitation_high_to_low.index[11] <= 9:
if min_precipitation*10 <= max_precipitation:
climatic_region = 'w'
else:
climatic_region = 'f'
else:
if min_precipitation*3 <= max_precipitation:
climatic_region = 's'
else:
climatic_region = 'f'
return climatic_region
# judge climatic zone of target city
def judge_ACDE(city_climatic_data):
climatic_division = {"climatic_zone":"", "climatic_region":"", "temperature":""}
max_temperature = city_climatic_data['temperature'][:12].max()
min_temperature = city_climatic_data['temperature'][:12].min()
max_precipitation = city_climatic_data['precipitation'][:12].max()
min_precipitation = city_climatic_data['precipitation'][:12].min()
if max_temperature < 10:
climatic_division["climatic_zone"] = "E"
if max_temperature >= 0:
climatic_division["climatic_region"] = "T"
else:
climatic_division["climatic_region"] = "F"
elif min_temperature >= 18:
climatic_division["climatic_zone"] = "A"
if min_precipitation >= 60:
climatic_division["climatic_region"] = "f"
else:
if (Decimal(-0.04)*Decimal(city_climatic_data['precipitation']['annual'])+100) > min_precipitation:
climatic_division["climatic_region"] = "w"
else:
climatic_division["climatic_region"] = "m"
elif min_temperature >= -3:
climatic_division["climatic_zone"] = "C"
climatic_division["climatic_region"] = judge_fsw(city_climatic_data)
if climatic_division["climatic_region"] == "f":
if max_temperature >= 22:
climatic_division["temperature"] = "a"
else:
climatic_division["temperature"] = "b"
else:
climatic_division["climatic_zone"] = "D"
climatic_division["climatic_region"] = judge_fsw(city_climatic_data)
return climatic_division
# judge climatic zone whether "B" or not
def judge_B(city_climatic_data,climatic_division):
if climatic_division["climatic_zone"] != "E":
annual_mean_temperature = city_climatic_data['temperature']['annual']
annual_precipitation = city_climatic_data['precipitation']['annual']
if climatic_division["climatic_region"] == "s":
arid_boundary = 20 * annual_mean_temperature
elif climatic_division["climatic_region"] == "f":
arid_boundary = 20 * (annual_mean_temperature+7)
elif climatic_division["climatic_region"] == "m":
arid_boundary = 20 * (annual_mean_temperature+7)
elif climatic_division["climatic_region"] == "w":
arid_boundary = 20 * (annual_mean_temperature+14)
if annual_precipitation < arid_boundary:
climatic_division["climatic_zone"] = "B"
if annual_precipitation < arid_boundary/2:
climatic_division["climatic_region"] = "W"
climatic_division["temperature"] = ""
else:
climatic_division["climatic_region"] = "S"
climatic_division["temperature"] = ""
else:
pass
return climatic_division
def show_result(city_index, city_climatic_data, climatic_division):
climatic_division_str = climatic_division["climatic_zone"]+\
climatic_division["climatic_region"]+\
climatic_division["temperature"]
print('=================================== result ====================================')
show_target_city(city_index)
if judge_north_south(city_climatic_data) == True:
print('北半球')
else:
print('南半球')
print('-------------------------------------------------------------------------------')
print(city_climatic_data)
print('-------------------------------------------------------------------------------')
print('気候区分: ', climatic_division_str)
print('気候区名: ', KOPPEN_CLIMATIC_DIVISION_LIST[climatic_division_str])
print("===============================================================================")
# main function
def main():
print(PROGRAM_DESCRIPTION)
city_index = get_city_index()
print(show_target_city(city_index))
print('対象地点のINDEX:', city_index)
city_climatic_data = gen_pandas_dataframe(city_index)
climatic_division = judge_ACDE(city_climatic_data)
climatic_division = judge_B(city_climatic_data,climatic_division)
show_result(city_index, city_climatic_data, climatic_division)
## main process
if __name__ == '__main__':
main()
## end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment