Python學習6之簡單實戰
Python學習6之簡單實戰
本系列文章用於以後編寫程式碼直接呼叫某些程式碼,也用作一個學習後的記錄,參考書籍為《Python資料分析與應用》,黃紅梅,張良均主編,張凌,施興,周東平副編,中國工信出版集團,人民郵電出版社,ISBN:9787115373045,文章附有程式碼和資料,學習起來較為容易
文章目錄
前言
本節講述航空公司客戶價值分析和財政收入預測分析,以及家用熱水器使用者行為分析與事件識別的實戰程式碼。不講述其具體理論,僅用作自我參考,如有興趣,自行查詢書籍進行學習。
一、航空公司客戶價值分析
1.瞭解航空公司現狀和客戶價值分析
這是程式設計之前必須考慮的東西,具體請參考書籍。
2.資料預處理
程式碼如下(示例):
import numpy as np
import pandas as pd
airline_data = pd.read_csv("air_data.csv",
encoding="gb18030") #匯入航空資料
print('原始資料的形狀為:',airline_data.shape)
#缺失值與異常值的處理
## 去除票價為空的記錄
exp1 = airline_data["SUM_YR_1"].notnull()
exp2 = airline_data["SUM_YR_2"].notnull()
exp = exp1 & exp2
airline_notnull = airline_data.loc[exp,:]
print('刪除缺失記錄後資料的形狀為:',airline_notnull.shape)
#只保留票價非零的,或者平均折扣率不為0且總飛行公里數大於0的記錄。
index1 = airline_notnull['SUM_YR_1'] != 0
index2 = airline_notnull['SUM_YR_2'] != 0
index3 = (airline_notnull['SEG_KM_SUM']> 0) & \
(airline_notnull['avg_discount'] != 0)
airline = airline_notnull[(index1 | index2) & index3]
print('刪除異常記錄後資料的形狀為:',airline.shape)
#選取並構建LRFMC模型的特徵
## 選取需求特徵
airline_selection = airline[["FFP_DATE","LOAD_TIME",
"FLIGHT_COUNT","LAST_TO_END",
"avg_discount","SEG_KM_SUM"]]
## 構建L特徵
L = pd.to_datetime(airline_selection["LOAD_TIME"]) - \
pd.to_datetime(airline_selection["FFP_DATE"])
L = L.astype("str").str.split().str[0]
L = L.astype("int")/30
## 合併特徵
airline_features = pd.concat([L,
airline_selection.iloc[:,2:]],axis = 1)
print('構建的LRFMC特徵前5行為:\n',airline_features.head())
# 標準化特徵
from sklearn.preprocessing import StandardScaler
data = StandardScaler().fit_transform(airline_features)
np.savez('airline_scale.npz',data)
print('標準化後LRFMC五個特徵為:\n',data[:5,:])
3.K-means演算法進行客戶分群
程式碼如下(示例):
## kmeans分類
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans #匯入kmeans演算法
airline_scale = np.load('airline_scale.npz')['arr_0']
k = 5 ## 確定聚類中心數
#構建模型
kmeans_model = KMeans(n_clusters = k,n_jobs=4,random_state=123)
fit_kmeans = kmeans_model.fit(airline_scale) #模型訓練
kmeans_model.cluster_centers_ #檢視聚類中心
kmeans_model.labels_ #檢視樣本的類別標籤
#統計不同類別樣本的數目
r1 = pd.Series(kmeans_model.labels_).value_counts()
print('最終每個類別的數目為:\n',r1)
二、財政收入預測分析
預測模型,主要是灰色預測和SVR迴歸預測。
1.瞭解背景
要對財政收入的預測背景和方法有簡單的瞭解,然後才可以尋找具體的預測方法。
2.分析資料特徵的相關性
這裡採用皮爾遜相關係數。
程式碼如下(示例):
#皮爾遜相關係數計算
import numpy as np
import pandas as pd
inputfile = 'data.csv' ## 輸入的資料檔案
data = pd.read_csv(inputfile) ## 讀取資料
## 保留兩位小數
print('相關係數矩陣為:',np.round(data.corr(method = 'pearson'), 2))
3.Lasso迴歸選取預測的相關特徵
Lasso迴歸的具體原理自行查詢,後續可能會補充。
程式碼如下(示例):
import numpy as np
import pandas as pd
from sklearn.linear_model import Lasso
inputfile = 'data.csv' #輸入的資料檔案
data = pd.read_csv(inputfile) #讀取資料
lasso = Lasso(1000) #呼叫Lasso()函式,設定λ的值為1000
lasso.fit(data.iloc[:,0:13],data['y'])
print('相關係數為:',np.round(lasso.coef_,5)) #輸出結果,保留五位小數
## 計算相關係數非零的個數
print('相關係數非零個數為:',np.sum(lasso.coef_ != 0))
mask = lasso.coef_ != 0 #返回一個相關係數是否為零的布林陣列
print('相關係數是否為零:',mask)
outputfile = 'new_reg_data.csv' #輸出的資料檔案
new_reg_data = data.iloc[:, mask] #返回相關係數非零的資料
new_reg_data.to_csv(outputfile) #儲存資料
print('輸出資料的維度為:',new_reg_data.shape) #檢視輸出資料的維度
4.灰色預測和SVR迴歸預測模型
注意灰色預測的包提前寫好,放在同一個資料夾裡。
首先灰色預測短期的資料特徵,然後再採用SVR迴歸預測。
程式碼如下(示例):
#灰色預測
import numpy as np
import pandas as pd
from GM11 import GM11 ## 引入自編的灰色預測函式
inputfile = 'new_reg_data.csv' ##輸入的資料檔案
inputfile1 = 'data.csv' ## 輸入的資料檔案
new_reg_data = pd.read_csv(inputfile) ## 讀取經過特徵選擇後的資料
data = pd.read_csv(inputfile1) ##讀取總的資料
new_reg_data.index = range(1994, 2014)
new_reg_data.loc[2014] = None
new_reg_data.loc[2015] = None
l = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
for i in l:
f = GM11(new_reg_data.loc[range(1994, 2014),i].as_matrix())[0]
new_reg_data.loc[2014,i] = f(len(new_reg_data)-1)#2014年預測結果
new_reg_data.loc[2015,i] = f(len(new_reg_data)) ##2015年預測結果
new_reg_data[i] = new_reg_data[i].round(2) ## 保留兩位小數
outputfile = 'new_reg_data_GM11.xls' ## 灰色預測後儲存的路徑
y = list(data['y'].values) ## 提取財政收入列,合併至新資料框中
y.extend([np.nan,np.nan])
new_reg_data['y'] = y
new_reg_data.to_excel(outputfile) ## 結果輸出
print('預測結果為:',new_reg_data.loc[2014:2015,:]) ##預測結果展示
import pandas as pd
import numpy as np
from sklearn.svm import LinearSVR
import matplotlib.pyplot as plt
from sklearn.metrics import explained_variance_score,\
mean_absolute_error,mean_squared_error,\
median_absolute_error,r2_score
inputfile = 'new_reg_data_GM11.xls' #灰色預測後儲存的路徑
data = pd.read_excel(inputfile) #讀取資料
feature = ['x1', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x13']
data_train = data.loc[range(0,19)].copy()#取2014年前的資料建模
data_mean = data_train.mean()
data_std = data_train.std()
data_train = (data_train - data_mean)/data_std #資料標準化
x_train = data_train[feature].as_matrix() #特徵資料
y_train = data_train['y'].as_matrix() #標籤資料
linearsvr = LinearSVR() #呼叫LinearSVR()函式
linearsvr.fit(x_train,y_train)
x = ((data[feature] - data_mean[feature])/ \
data_std[feature]).as_matrix() #預測,並還原結果。
data[u'y_pred'] = linearsvr.predict(x) * \
data_std['y'] + data_mean['y']
## SVR預測後儲存的結果
outputfile = 'new_reg_data_GM11_revenue.xls'
data.to_excel(outputfile)
print('真實值與預測值分別為:',data[['y','y_pred']])
print('預測圖為:',data[['y','y_pred']].plot(style=['b-o','r-*']))
三、家用熱水器使用者行為分析與事件識別
一種比較應用於實際的資料分析吧。
1.瞭解背景
學習之前要對家用熱水器資料有一個基本的瞭解,對該問題有基本的瞭解。
2.資料預處理
刪除冗餘特徵,劃分用水事件,確定單次用水事件用水時長閾值。
程式碼如下(示例):
#刪除冗餘特徵
import pandas as pd
import numpy as np
data = pd.read_excel('original_data.xls')
print('初始狀態的資料形狀為:', data.shape)
# 刪除熱水器編號,有無水流,節能模式
data.drop(labels = ["熱水器編號","有無水流","節能模式"],
axis = 1,inplace = True)
print('刪除冗餘特徵後的資料形狀為:', data.shape)
data.to_csv('water_heart.csv',index = False)
# 劃分用水事件
threshold = pd.Timedelta('4 min') #閾值為分鐘
data['發生時間'] = pd.to_datetime(data['發生時間'],
format = '%Y%m%d%H%M%S') # 轉換時間格式
data = data[data['水流量'] > 0] #只要流量大於0的記錄
#相鄰時間向前差分,比較是否大於閾值
sjKs = data['發生時間'].diff() > threshold
sjKs.iloc[0] = True # 令第一個時間為第一個用水事件的開始事件
sjJs = sjKs.iloc[1:] # 向後差分的結果
# 令最後一個時間作為最後一個用水事件的結束時間
sjJs = pd.concat([sjJs,pd.Series(True)])
# 建立資料框,並定義用水事件序列
sj = pd.DataFrame(np.arange(1,sum(sjKs)+1),columns = ["事件序號"])
sj["事件起始編號"] = data.index[sjKs == 1]+1 # 定義用水事件的起始編號
sj["事件終止編號"] = data.index[sjJs == 1]+1 # 定義用水事件的終止編號
print('當閾值為4分鐘的時候事件數目為:',sj.shape[0])
sj.to_csv('sj.csv',index = False)
# 確定單次用水事件時長閾值
n = 4 #使用以後四個點的平均斜率
threshold = pd.Timedelta(minutes = 5) #專家閾值
data['發生時間'] = pd.to_datetime(data['發生時間'],
format = '%Y%m%d%H%M%S')
data = data[data['水流量'] > 0] #只要流量大於0的記錄
# 自定義函式:輸入劃分時間的時間閾值,得到劃分的事件數
def event_num(ts):
d = data['發生時間'].diff() > ts #相鄰時間作差分,比較是否大於閾值
return d.sum() + 1 #這樣直接返回事件數
dt = [pd.Timedelta(minutes = i) for i in np.arange(1, 9, 0.25)]
h = pd.DataFrame(dt, columns = ['閾值']) #轉換資料框,定義閾值列
h['事件數'] = h['閾值'].apply(event_num) #計算每個閾值對應的事件數
h['斜率'] = h['事件數'].diff()/0.25 #計算每兩個相鄰點對應的斜率
#往前取n個斜率絕對值平均作為斜率指標
h['斜率指標']= h['斜率'].abs().rolling(4).mean()
ts = h['閾值'][h['斜率指標'].idxmin() - n]
#用idxmin返回最小值的Index,由於rolling_mean()計算的是前n個斜率的絕對值平均
#所以結果要進行平移(-n)
if ts > threshold:
ts = pd.Timedelta(minutes = 4)
print('計算出的單次用水時長的閾值為:',ts)
3.構建用水行為特徵並篩選用水事件
主要有構建用水時長與頻率特徵,用水量與波動特徵,篩選候選洗浴事件。
程式碼如下(示例):
# 構建用水時長與頻率特徵
import pandas as pd
import numpy as np
# 讀取熱水器使用資料記錄
data = pd.read_excel('water_hearter.xlsx')
# 讀取用水事件記錄
sj = pd.read_csv('sj.csv',encoding = 'utf8')
data["發生時間"] = pd.to_datetime(data["發生時間"],
format = "%Y%m%d%H%M%S") # 轉換時間格式
# 構造特徵:總用水時長
timeDel = pd.Timedelta("1 sec")
sj["事件開始時間"] = data.iloc[sj["事件起始編號"]-1,0].values- timeDel
sj["事件結束時間"] = \
data.iloc[sj["事件終止編號"]-1,0].values + timeDel
sj['洗浴時間點'] = [i.hour for i in sj["事件開始時間"]]
tmp1 = sj["事件結束時間"] - sj["事件開始時間"]
sj["總用水時長"] = np.int64(tmp1)/1000000000
# 構造用水停頓事件
# 構造特徵“停頓開始時間”、“停頓結束時間”
# 停頓開始時間指從有水流到無水流,停頓結束時間指從無水流到有水流
for i in range(len(data)-1):
if (data.loc[i,"水流量"] != 0) & (data.loc[i + 1,"水流量"] == 0) :
data.loc[i + 1,"停頓開始時間"] = \
data.loc[i +1, "發生時間"] - timeDel
if (data.loc[i,"水流量"] == 0) & (data.loc[i + 1,"水流量"] != 0) :
data.loc[i,"停頓結束時間"] = \
data.loc[i , "發生時間"] + timeDel
# 提取停頓開始時間與結束時間所對應行號,放在資料框Stop中
indStopStart = data.index[data["停頓開始時間"].notnull()]+1
indStopEnd = data.index[data["停頓結束時間"].notnull()]+1
Stop = pd.DataFrame(data = {"停頓開始編號":indStopStart[:-1],
"停頓結束編號":indStopEnd[1:]})
# 計算停頓時長,並放在資料框stop中,停頓時長=停頓結束時間-停頓結束時間
tmp2 = data.loc[indStopEnd[1:]-1,"停頓結束時間"]
tmp3 = data.loc[indStopStart[:-1]-1,"停頓開始時間"]
tmp4 = tmp2.values-tmp3.values
Stop["停頓時長"] = np.int64(tmp4)/1000000000
# 將每次停頓與事件匹配,停頓的開始時間要大於事件的開始時間,
# 且停頓的結束時間要小於事件的結束時間
for i in range(len(sj)):
Stop.loc[(Stop["停頓開始編號"] > sj.loc[i,"事件起始編號"]) &
(Stop["停頓結束編號"] < sj.loc[i,"事件終止編號"]),
"停頓歸屬事件"] = i+1
# 刪除停頓次數為0的事件
Stop = Stop[Stop["停頓歸屬事件"].notnull()]
# 構造特徵 用水事件停頓總時長、停頓次數、停頓平均時長、
# 用水時長,用水/總時長
stopAgg = Stop.groupby("停頓歸屬事件").agg({"停頓時長":sum,
"停頓開始編號":len})
sj.loc[stopAgg.index - 1,"總停頓時長"] = \
stopAgg.loc[:,"停頓時長"].values
sj.loc[stopAgg.index-1,"停頓次數"] = \
stopAgg.loc[:,"停頓開始編號"].values
sj.fillna(0,inplace=True) # 對缺失值用0插補
stopNo0 = sj["停頓次數"] != 0 # 判斷用水事件是否存在停頓
sj.loc[stopNo0,"平均停頓時長"] = \
sj.loc[stopNo0,"總停頓時長"]/sj.loc[stopNo0,"停頓次數"]
sj.fillna(0,inplace=True) # 對缺失值用0插補
sj["用水時長"] = sj["總用水時長"] - sj["總停頓時長"] # 定義特徵用水時長
# 定義特徵 用水/總時長
sj["用水/總時長"] = sj["用水時長"] / sj["總用水時長"]
print('用水事件用水時長與頻率特徵構造完成後資料的特徵為:\n',sj.columns)
print('用水事件用水時長與頻率特徵構造完成後資料的前5行5列特徵為:\n',
sj.iloc[:5,:5])
# 構建用水量與波動特徵
data["水流量"] = data["水流量"] / 60 # 原單位L/min,現轉換為L/sec
sj["總用水量"] = 0 # 給總用水量賦一個初始值0
for i in range(len(sj)):
Start = sj.loc[i,"事件起始編號"]-1
End = sj.loc[i,"事件終止編號"]-1
if Start != End:
for j in range(Start,End):
if data.loc[j,"水流量"] != 0:
sj.loc[i,"總用水量"] = (data.loc[j + 1,"發生時間"] -
data.loc[j,"發生時間"]).seconds* \
data.loc[j,"水流量"] + \
sj.loc[i,"總用水量"]
sj.loc[i,"總用水量"] = sj.loc[i,"總用水量"] + \
data.loc[End,"水流量"] * 2
else:
sj.loc[i,"總用水量"] = data.loc[Start,"水流量"] * 2
sj["平均水流量"] = sj["總用水量"] / sj["用水時長"] # 定義特徵 平均水流量
# 構造特徵:水流量波動
# 水流量波動=∑(((單次水流的值-平均水流量)^2)*持續時間)/用水時長
sj["水流量波動"] = 0 # 給水流量波動賦一個初始值0
for i in range(len(sj)):
Start = sj.loc[i,"事件起始編號"] - 1
End = sj.loc[i,"事件終止編號"] - 1
for j in range(Start,End + 1):
if data.loc[j,"水流量"] != 0:
slbd = (data.loc[j,"水流量"] - sj.loc[i,"平均水流量"])**2
slsj = (data.loc[j + 1,"發生時間"] -
data.loc[j,"發生時間"]).seconds
sj.loc[i,"水流量波動"] = \
slbd * slsj + sj.loc[i,"水流量波動"]
sj.loc[i,"水流量波動"] = \
sj.loc[i,"水流量波動"] / sj.loc[i,"用水時長"]
# 構造特徵:停頓時長波動
# 停頓時長波動=∑(((單次停頓時長-平均停頓時長)^2)*持續時間)/總停頓時長
sj["停頓時長波動"] = 0 # 給停頓時長波動賦一個初始值0
for i in range(len(sj)):
# 當停頓次數為0或1時,停頓時長波動值為0,故排除
if sj.loc[i,"停頓次數"] > 1:
for j in Stop.loc[Stop["停頓歸屬事件"] == \
(i+1),"停頓時長"].values:
sj.loc[i,"停頓時長波動"] = \
((j - sj.loc[i,"平均停頓時長"])**2) * j + \
sj.loc[i,"停頓時長波動"]
sj.loc[i,"停頓時長波動"] = \
sj.loc[i,"停頓時長波動"] / sj.loc[i,"總停頓時長"]
print('用水量和波動特徵構造完成後資料的特徵為:\n',sj.columns)
print('用水量和波動特徵構造完成後資料的前5行5列特徵為:\n',
sj.iloc[:5,:5])
# 篩選候選洗浴事件
sj_bool = (sj['用水時長'] >100) & \
(sj['總用水時長'] > 120) & (sj['總用水量'] > 5)
sj_final = sj.loc[sj_bool,:]
sj_final.to_excel('sj_final.xlsx',index = False)
print('篩選出候選洗浴事件前的資料形狀為:',sj.shape)
print('篩選出候選洗浴事件後的資料形狀為:',sj_final.shape)
總結
提示:本文章簡單介紹了三個實戰專案,主要是程式碼,具體介紹如有興趣,自行檢視書籍,所用所有資料在百度網盤:
連結: https://pan.baidu.com/s/1Kj5Y2wAgDlwMGRlh9kED0Q 提取碼: 2zqm
資料連結
相關文章
- 《ElasticSearch6.x實戰教程》之簡單的APIElasticsearchAPI
- Django 實戰練習-簡單部落格Django
- 實戰表單驗證學習
- 《ElasticSearch6.x實戰教程》之簡單搜尋、Java客戶端(上)ElasticsearchJava客戶端
- python如何實現簡單的爬蟲功能?Python學習教程!Python爬蟲
- 演算法學習之簡單排序演算法排序
- Python學習筆記——爬蟲之Scrapy專案實戰Python筆記爬蟲
- Python3 基礎學習之數值簡單運算Python
- 雲課堂 Python學習簡單示例Python
- 更快學習 JS 的 6 個簡單思維技巧JS
- 深度學習之PyTorch實戰(4)——遷移學習深度學習PyTorch遷移學習
- MySQL入門學習之——實戰XtraBackupMySql
- MySQL入門學習之——實戰mysqldumpMySql
- Python的學習(十四)---- 實現簡單的HTTP伺服器PythonHTTP伺服器
- Electron學習(三)之簡單互動操作
- Nancy簡單實戰之NancyMusicStore(五):部署上線NaN
- 《深度學習Python》核心技術實戰深度學習Python
- [action]tensorflow深度學習實戰 (4) 實現簡單卷積神經網路深度學習卷積神經網路
- 簡單學習jsJS
- Git簡單學習Git
- gin簡單學習
- Flutter mvvm簡單實戰FlutterMVVM
- Kafka實戰-簡單示例Kafka
- JavaScript ES6 async/await的簡單學習demoJavaScriptAI
- Nancy簡單實戰之NancyMusicStore(六):寫在最後NaN
- SpringMVC學習筆記之---簡單入門SpringMVC筆記
- React Native學習之 ListView 的簡單使用React NativeView
- RabbitMQ學習之(四)_PHP操作RabbitMQ簡單DemoMQPHP
- SG學習筆記之RMAN簡單歸納筆記
- Python 開發簡單爬蟲 (學習筆記)Python爬蟲筆記
- Python爬蟲學習(5): 簡單的爬取Python爬蟲
- 學習Python的日子 Python(6)Python
- JErasure庫簡單學習
- Python學習第6天Python
- webpack 學習筆記:實戰之 babel 編碼Web筆記Babel
- K8S系列學習之Pod實戰K8S
- 基於python的大資料分析實戰學習筆記-pandas之DataFramePython大資料筆記
- Python入門方法--簡單總結+學習方式思考Python