【前言】
每年夏季,颱風就如期而至。今年八月份,「風王」利奇馬真的如脫韁野馬,讓大家見識到颱風的可怕之處。
這次收集到1945~2015年在中國登陸的所有颱風數據,並通過Python對這些數據進行可視化分析,希望能得到一些有意思的結論。
【數據來源】
該數據集來自於上海追風團隊,在其官網颱風數據中心下載。
網站提到某些數據年代久遠,會有缺失和誤差,請甄別使用。所以這裡無法對數據的精確性和完整性做保證,主要是想運用python對數據做分析展示,看看颱風在等級、地點、時間上的分布。槓精勿擾~
部分數據展示
【分析工具】
本文使用python及其第三方庫做分析展示,分析平臺是Jupyter notebook,用到爬蟲、詞雲、可視化、地理空間分析等技術。
主要工具:Python 3.6、pandas、numpy、matplotlib、seaborn、urllib、geopandas、wordcloud
【分析流程】
1、導入相關庫
# 導入相關庫import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport geopandas import seaborn as snsfrom urllib import requestimport refrom shapely.geometry import LineString,Pointfrom urllib import parsefrom urllib.request import urlopenimport hashlibimport jsonfrom wordcloud import WordCloudimport warningswarnings.filterwarnings('ignore')# 顯示中文標籤plt.rc('font', family='SimHei', size=18)sns.set()%matplotlib inline2、加載數據集
data = pd.read_excel(r'case\taifeng.xlsx')data.shape3、查看數據集
4、數據整理
我們可以看到數據集裡只有登陸地址,沒有確切的經緯度信息 。
這裡需要通過地理編碼的方式獲取經緯度,使用的是百度地圖API。# 地理編碼,通過登陸地址信息得到經、緯度def get_coor(address): # 需填入自己申請應用後生成的ak ak = 'mcH6sBNaAfsbkSndFI5zO90j9wUpRMFy1' url = 'http://api.map.baidu.com/geocoder/v2/?address=' output = 'json' add = parse.quote(address) # 本文城市變量為中文,為防止亂碼,先用quote進行編碼 url2 = url + add + '&output=' + output + "&ak=" + ak req = urlopen(url2) response = req.read().decode() #將返回的數據轉化成json格式 responseJson = json.loads(response) # 獲取經緯度 lon = responseJson.get('result')['location']['lng'] lat = responseJson.get('result')['location']['lat'] return (lat,lon)
# 添加經、緯度欄位data['coor'] = data['登陸地點'].apply(lambda x:get_coor(x))data['lat'] = data['coor'].apply(lambda x: list(x)[0])data['lon'] = data['coor'].apply(lambda x: list(x)[1])獲取到登陸經緯度信息後,再通過地理逆編碼的方式獲取省、市、區縣三級信息 。
有人可能會覺得「登陸地點」欄位已經有地址信息,為什麼不直接截取欄位?往往地址信息比較複雜,沒有辦法用簡單的正則表達式去截取,而地理逆編碼的方式卻能很好的捕捉省、市、區縣三級信息。def get_address(lon,lat): your_ak = 'mcH6sBNaAfsbkSndFI5zO90j9wUpRMFy1' url = 'http://api.map.baidu.com/geocoder/v2/?callback=renderReverse&extensions_town=true&location={},{}&output=json&pois=1&latest_admin=1&ak={}'.format(lat,lon,your_ak) rp = request.urlopen(url).read().decode('utf-8') rp = re.findall(r"\((.*)\)",rp)[0] rpjson= json.loads(rp) province = rpjson['result']['addressComponent']['province'] city = rpjson['result']['addressComponent']['city'] district = rpjson['result']['addressComponent']['district'] data = (province, city, district) return data
data['area'] = data['coor'].apply(lambda x:get_address(x[1],x[0]))data['省'] = data['area'].apply(lambda x:x[0])data['市'] = data['area'].apply(lambda x:x[1])data['區縣'] = data['area'].apply(lambda x:x[2])5、颱風登陸地點分布
使用geopandas將颱風登陸點放到地圖上,這裡會用到經、緯度數據。
xy = [Point(xy) for xy in zip(data.lon,data.lat)]geo_data = geopandas.GeoDataFrame(data,geometry=xy)gdf = geopandas.read_file(r"case\exportedBoundaries_shp_single_land_20190911_031017\Taiwan_AL2-AL4.shp")ax = gdf.plot(figsize=(20, 20), alpha=0.5, edgecolor='white',color='g',linewidth=1)geo_data.plot(ax=ax,color='red',markersize=7)plt.rc('font', family='SimHei', size=18)plt.title('1945-2015 全國沿海省份颱風登陸地點分布圖',size=30)plt.show()
6、颱風登陸地點詞雲展示
詞雲字體越大代表登陸該地點的颱風數量越多。
words = ','.join(data['省'].values.tolist())wc = WordCloud( background_color="white", max_words=300, font_path='./fonts/simhei.ttf', min_font_size=5, max_font_size=100, width=500 )x = wc.generate(words)image = x.to_image()image
words = ','.join(data['市'].values.tolist())wc = WordCloud( background_color="white", max_words=300, font_path='./fonts/simhei.ttf', min_font_size=5, max_font_size=100, width=500 )x = wc.generate(words)image = x.to_image()image
words = ','.join(data['區縣'].values.tolist())wc = WordCloud( background_color="white", max_words=300, font_path='./fonts/simhei.ttf', min_font_size=5, max_font_size=100, width=500 )x = wc.generate(words)image = x.to_image()image
7、數據可視化分析
# 新建data_1data_1 = data[['登陸時間','登陸強度','巔峰強度','省']].dropna()data_1['登陸等級'] = data_1['登陸強度'].apply(lambda x:int(re.match('\d+',str(x).split(',')[0]).group()))data_1['巔峰等級'] = data_1['巔峰強度'].apply(lambda x:int(re.match('\d+',str(x).split(',')[0]).group()))data_1['登陸年份'] = data_1['登陸時間'].apply(lambda x:x.year)data_1['登陸月份'] = data_1['登陸時間'].apply(lambda x:x.month)plt.figure(figsize=(18,6))sns.swarmplot(x='省',y='登陸等級',data=data_1,palette='Set1')plt.title("1945-2015 各省颱風登陸等級分類散點圖(點數多少代表颱風數量)",size=20)plt.show()
year_counts = data['登陸時間'].apply(lambda x:x.year).value_counts().sort_index()plt.figure(figsize=(15,6))plt.plot(year_counts,lw=2)plt.plot(year_counts,'ro',color='b')x = year_counts.index.tolist()y_mean = [year_counts.mean()]*year_counts.shape[0]plt.plot(x,y_mean,'--')plt.xlabel('年份')plt.ylabel('次數')plt.rc('font', family='SimHei', size=18) plt.title('1945-2015 全國每年颱風登陸數量',size=20)plt.show()
data_3 = data_1.groupby(['登陸月份','登陸等級'],as_index=False)['登陸時間'].count()data_3 = data_3.rename(columns={'登陸時間':'登錄次數'})data_3_pivot = data_3.pivot('登陸等級','登陸月份','登錄次數')plt.figure(figsize=(8,6))sns.heatmap(data_3_pivot)plt.title('1945-2015 全國颱風登陸次數熱力圖(按月份-登陸等級)',size=20)plt.show()
plt.figure(figsize=(8,6))sns.boxplot(x='登陸月份',y='登陸等級',data=data_3)plt.title('1945-2015 全國颱風登陸等級分布箱圖',size=20)plt.show()
data_2 = data_1.groupby(['登陸月份','巔峰等級'],as_index=False)['登陸時間'].count()data_2 = data_2.rename(columns={'登陸時間':'登錄次數'})data_2_pivot = data_2.pivot('巔峰等級','登陸月份','登錄次數')plt.figure(figsize=(8,6))sns.heatmap(data_2_pivot)plt.title('1945-2015 全國颱風登陸次數熱力圖(按月份-巔峰等級)',size=20)plt.show()
plt.figure(figsize=(8,6))sns.boxplot(x='登陸月份',y='巔峰等級',data=data_2)plt.title('1945-2015 全國颱風巔峰等級箱圖',size=20)plt.show()【結論】
從地理位置上看,1945-2015 颱風主要登陸地點集中在廣東省、海南省、臺灣省,在臺灣省登陸的颱風等級較高,廣東省數量最多。湛江市和臺東縣是颱風最喜歡登陸的市、縣。
從時間上看,年平均登陸颱風數量9次左右,主要集中在8、9月份,8月份的颱風等級中位數較高,並且強颱風主要出現在9月份前後。
想要該項目完整文件(含代碼、颱風數據、地圖)的童鞋,在公眾號後臺回覆:颱風Python大數據分析
data creat value