1. 資料擷取與匯入¶
In [1]:
# 首先先將資料(.csv檔)讀入
#
import pandas as pd
df = pd.read_csv("台北市10401-10602住宅竊盜點位資訊.csv", encoding='big5')
print('筆數', df.count())
df[:10]
Out[1]:
2. 資料預處理¶
In [2]:
# 資料清理
# 由檔案結構可知,「案類」欄的資料都是"住宅竊盜",所以可以刪除之。
#
del df['案類']
df[:10]
Out[2]:
In [3]:
# 我們可以利用'發生地點'產生'發生地點行政區',藉此以行政區為基準做出統計資料。
# 以 df['發生地點']中字串之第4~6個字,作為 df['發生地點行政區']之內容。
#
for i in range(len(df)):
# df[i:i+1]['發生地點行政區'] = df['發生地點'][i][3:6]
df.loc[i,'發生地點行政區'] = df['發生地點'][i][3:6]
df[:10]
Out[3]:
In [4]:
# 去除 '發生地點' 欄位
del df['發生地點']
df[:10]
Out[4]:
In [5]:
# 聚合函數
# A. 得出在每個行政區、在 101年06月06日 ~ 106年2月27日之間,每日發生的住宅竊盜件數
#
df2 = df.groupby(['發生地點行政區','發生日期']).count()
del df2['發生時段']
df2 = df2.rename(columns = {'編號':'件數'})
df2[:15]
Out[5]:
In [6]:
# 長條圖
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'SimHei'
df2.plot(kind='bar', title='在每個行政區、在 97年06月09日 ~ 106年2月27日之間,每日發生的住宅竊盜件數', figsize=(400,10))
Out[6]:
In [7]:
# 聚合函數
# B. 得出在 97年06月09日 ~ 106年2月27日之間,不同時段發生的住宅竊盜件數
# df_ti (time inmterval)
#
df_ti = df.groupby('發生時段').count()
del df_ti['發生日期'],df_ti['發生地點行政區']
df_ti = df_ti.rename(columns = {'編號':'件數'})
df_ti['比率'] = round(df_ti['件數']/df_ti['件數'].sum()*100, 2)
df_ti
Out[7]:
In [8]:
# 長條圖
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'SimHei'
df_ti.sort_values(by='件數', ascending=False).plot(kind='bar', title='台北市 97年06月09日 ~ 106年2月27日之間,不同時段發生的住宅竊盜件數', figsize=(10,5), fontsize=19)
Out[8]:
In [9]:
# C. 樞紐分析表
#
df_pt = df.pivot_table(values='編號',index='發生日期', columns='發生地點行政區', aggfunc='count',fill_value='0')
print('台北市 97年06月09日 ~ 106年2月27日之間,各行政區發生的住宅竊盜件數')
df_pt[:10]
Out[9]:
In [43]:
# D. 樞紐分析表 2
#
df_pt2 = df.pivot_table(values='編號',index='發生時段', columns='發生地點行政區', aggfunc='count',fill_value='0')
print('台北市 97年06月09日 ~ 106年2月27日之間,各行政區相對於發生時段的住宅竊盜件數')
df_pt2.head()
Out[43]:
In [46]:
df_pt2.plot(kind='area', title='台北市 97年06月09日 ~ 106年2月27日之間,各行政區相對於發生時段的住宅竊盜件數 (堆疊面積圖)', figsize=(15,10), fontsize=17)
Out[46]:
4. 資料分析⽅法¶
In [10]:
# A. 統計分析
# 各行政區住宅竊盜件數總和及統計
#
df3 = df.groupby('發生地點行政區').count()
del df3['發生日期'],df3['發生時段']
df3 = df3.rename(columns = {'編號':'件數'})
df3 = df3.sort_values('件數', ascending=False)
df3['比率'] = round(df3['件數']/df3['件數'].sum()*100, 2)
df3
Out[10]:
In [11]:
# 平均、最大、最小
#
print('最多件數', df3['件數'].max())
print('最少件數', df3['件數'].min())
print('平均件數', df3['件數'].mean())
In [12]:
df3.plot(kind='bar', title='台北市住宅竊盜件數長條圖 (97年06月09日 ~ 106年2月27日)', fontsize=15, figsize=(15,5))
Out[12]:
In [13]:
df3['件數'].plot(kind='pie', title='台北市住宅竊盜件數圓餅圖 (97年06月09日 ~ 106年2月27日)', autopct='%1.1f%%', startangle=270, fontsize=14, figsize=(10,10))
Out[13]:
In [14]:
# B. 時間序列分析
# df_ts (time series)
df_ts = df.groupby('發生日期').count()
del df_ts['發生時段'],df_ts['發生地點行政區']
df_ts = df_ts.rename(columns = {'編號':'件數'})
df_ts[:10]
Out[14]:
In [15]:
df_ts['發生日期'] = df_ts.index + 19110000 # 轉換民國年為西元年
df_ts[:10]
Out[15]:
In [16]:
df_ts = df_ts.set_index(df_ts['發生日期'], drop=True)
del df_ts['發生日期']
df_ts[:10]
Out[16]:
In [17]:
df_ts.index = pd.to_datetime(df_ts.index, format='%Y%m%d')
In [18]:
type(df_ts.index)
Out[18]:
In [19]:
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'SimHei'
df_ts.plot(kind='line', figsize=(15,5), fontsize=17)
Out[19]:
In [20]:
# 以年計算
df_ts2 = df_ts.groupby(df_ts.index.year).count()
df_ts2
Out[20]:
In [21]:
df_ts2.plot(kind='line', figsize=(15,5), fontsize=17)
Out[21]:
In [22]:
# 以季區分
df_ts_Q = df_ts.resample('Q-DEC').count()
df_ts_Q[df_ts_Q.index.year > 2014]
Out[22]:
In [23]:
df_ts_Q[df_ts_Q.index.year > 2014].plot(kind='line', figsize=(15,5), fontsize=17)
Out[23]:
In [24]:
# 以月區分
df_ts_M = df_ts.resample('M').count()
df_ts_M[df_ts_M.index.year > 2014][:10]
Out[24]:
In [25]:
df_ts_M[df_ts_M.index.year > 2014].plot(kind='line', figsize=(20,5), fontsize=17)
Out[25]:
5. 視覺化¶
In [26]:
# A. 以行政區區分的住宅竊盜件數之視覺化 折線圖
#
df_pt1 = df_pt # 使用樞紐分析表為資料來源
df_pt1['發生日期'] = df_pt1.index + 19110000 # 轉換民國年為西元年
df_pt1 = df_pt1.set_index(df_pt1['發生日期'], drop=True) # 改 index 為 西元年
del df_pt1['發生日期'] # 刪除原民國年欄位
df_pt1.index = pd.to_datetime(df_pt1.index, format='%Y%m%d') # 將 index 改為 datatime type
df_pt1[:10]
Out[26]:
In [27]:
t = df_pt1.apply(pd.to_numeric, errors='ignore') # 將 values 轉成數值型態,以便繪圖。
In [28]:
t[t.index.year > 2014].plot(kind='line',title='台北市住宅竊盜件數(依行政區) 104年01月-106年02月 折線圖', subplots=True, figsize=(15,20), fontsize=17)
Out[28]:
In [29]:
# B. 台北市住宅竊盜件數(依行政區)之視覺化 104年01月-106年02月(以月來分) 長條圖
#
t_M = t[t.index.year > 2014].resample('M').sum()
t_M[:10]
Out[29]:
In [30]:
t_M.plot(kind='bar',title='台北市住宅竊盜件數(依行政區) 104年01月-106年02月 長條圖',stacked=True, figsize=(20,8), fontsize=17)
Out[30]:
6. 基礎機器學習 Machine Learning - 決策分類樹¶
In [31]:
# use df as data source
df.head()
Out[31]:
In [32]:
# transformation of '發生時段'
# 將'發生時段'轉換成數字,作為一項特徵。
#
time_to_code = {'01~03':1,'04~06':2,'07~09':3,'10~12':4,'13~15':5,'16~18':6,'19~21':7,'22~24':8}
df_time = df
df_time['time_code'] = df_time['發生時段'].map(time_to_code)
df_time.head()
Out[32]:
In [33]:
# 從'發生日期'轉成 weekday,並以數字表示,作為一項特徵。
# 增加一欄 weekday 欄位,表示該日為星期幾。
df_time1 = df_time
df_time1['發生日期'] = df_time1['發生日期'] + 19110000 # 轉換民國年為西元年
df_time1 = df_time1.set_index(df_time1['發生日期'], drop=True) # 改 index 為 西元年
del df_time1['發生日期'] # 刪除原民國年欄位
df_time1.index= pd.to_datetime(df_time1.index, format='%Y%m%d') # 將 index 改為 datatime type
df_time1['weekday'] = df_time1.index.weekday # 新增 weekday 欄位,表示該日為星期幾。
df_time1.head()
Out[33]:
Gini¶
In [34]:
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(criterion='gini', max_depth=5)
tree.fit(df_time1[['weekday','time_code']], df_time1[['發生地點行政區']])
Out[34]:
In [35]:
from sklearn.tree import export_graphviz
export_graphviz(tree, out_file="tree.dot", feature_names=['發生日期','time_code'],
class_names=['中山區','中正區','信義區','內湖區','北投區','南港區','士林區','大同區','大安區','文山區','松山區','萬華區'],)
In [36]:
!dot -Tpng tree.dot -o tree.png
In [37]:
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
%matplotlib inline
img = mpimg.imread('tree.png')
fig = plt.figure(figsize=(20,20))
plt.imshow(img)
Out[37]:
In [38]:
tree.feature_importances_.tolist()
df_tree = pd.DataFrame({'feature':['weekday','time_code'],'feature_importance':tree.feature_importances_.tolist()})
df_tree = df_tree.sort_values(by=['feature_importance'],ascending=False).reset_index(drop=True)
df_tree.head()
Out[38]:
In [39]:
def autolabel(rects):
# attach some text labels
for rect in rects:
height = rect.get_height()
plt.text(rect.get_x()+rect.get_width()/2., 1.02*height, '%f'%float(height),
ha='center', va='bottom')
In [40]:
import matplotlib
import matplotlib.pyplot as plt
plt.style.use('ggplot')
fig = plt.figure(figsize=(8,4))
#中文字體 font = matplotlib.font_manager.FontProperties(fname='wt011.ttf')
plt.rcParams['font.family']='SimHei'
gini = plt.bar(df_tree.index,df_tree['feature_importance'],align='center')
plt.xlabel('Feature') #X軸名稱
plt.ylabel('Feature Importance') #Y軸名稱
plt.xticks(df_tree.index, df_tree['feature']) #X軸項目名稱
autolabel(gini)
#for i in range(len(df.index)):
# plt.annotate(round(df['gini_importance'][i],3),xy=(df.index[i],df['gini_importance'][i]),
# xytext=(df.index[i],df['gini_importance'][i]))
plt.show()
K-means Clustering¶
In [41]:
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
df_time1.time_code = df_time1.time_code.astype(float) #traform into float type
df_time1.weekday = df_time1.weekday.astype(float) #traform into float type
X = df_time1[['time_code','weekday']].values #tranform DataFrame to ndarray Matrix
km = KMeans(n_clusters=4)
y_pred = km.fit_predict(X)
plt.figure(figsize=(10, 6))
plt.xlabel('Time code')
plt.ylabel('Weekday')
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()
In [42]:
# df_time1.to_csv('df_time1.csv') # save data to 'df_time1.csv' for further research.
No comments:
Post a Comment