1、讀取資料檔案
迴歸分析問題所用的資料都是儲存在資料檔案中的,首先就要從資料檔案讀取資料。
資料檔案的格式很多,最常用的是 .csv,.xls 和 .txt 檔案,以及 sql 資料庫檔案的讀取 。
使用 pandas 從資料檔案匯入資料的程式最為簡單,示例如下:
(1)讀取 .csv 檔案:
df = pd.read_csv("./example.csv", engine="python", encoding="utf_8_sig")
# engine="python"允許處理中文路徑,encoding="utf_8_sig"允許讀取中文資料
(2)讀取 .xls 檔案:
df = pd.read_excel("./example.xls", sheetname='Sheet1', header=0, encoding="utf_8_sig")
# sheetname 表示讀取的sheet,header=0 表示首行為標題行, encoding 表示編碼方式
(3)讀取 .txt 檔案:
df = pd.read_table("./example.txt", sep="\t", header=None)
# sep 表示分隔符,header=None表示無標題行,第一行是資料
2、資料檔案的拆分與合併
統計迴歸所需處理的資料量可能非常大,必要時需對檔案進行拆分或合併,也可以用 pandas 進行處理,示例如下:
(1)將 Excel 檔案分割為多個檔案
# 將 Excel 檔案分割為多個檔案
import pandas as pd
dfData = pd.read_excel('./example.xls', sheetname='Sheet1')
nRow, nCol = dfData.shape # 獲取資料的行列
# 假設資料共有198,000行,分割為 20個檔案,每個檔案 10,000行
for i in range(0, int(nRow/10000)+1):
saveData = dfData.iloc[i*10000+1:(i+1)*10000+1, :] # 每隔 10,000
fileName= './example_{}.xls'.format(str(i))
saveData.to_excel(fileName, sheet_name = 'Sheet1', index = False)
(2)將 多個 Excel 檔案合併為一個檔案
# 將多個 Excel 檔案合併為一個檔案
import pandas as pd
## 兩個 Excel 檔案合併
#data1 = pd.read_excel('./example0.xls', sheetname='Sheet1')
#data2 = pd.read_excel('./example1.xls', sheetname='Sheet1')
#data = pd.concat([data1, data2])
# 多個 Excel 檔案合併
dfData = pd.read_excel('./example0.xls', sheetname='Sheet1')
for i in range(1, 20):
fileName = './example_{}.xls'.format(str(i))
dfNew = pd.read_excel(fileName)
dfData = pd.concat([dfData, dfNew])
dfData.to_excel('./example', index = False)
3、資料的預處理
在實際工作中,在開始建立模型和擬合分析之前,還要對原始資料進行資料預處理(data preprocessing),主要包括:缺失值處理、重複資料處理、異常值處理、變數格式轉換、訓練集劃分、資料的規範化、歸一化等。
資料預處理的很多內容已經超出了 Statsmodels 的範圍,在此只介紹最基本的方法:
(1)缺失資料的處理
匯入的資料存在缺失是經常發生的,最簡單的處理方式是刪除缺失的資料行。使用 pandas 中的 .dropna() 刪除含有缺失值的行或列,也可以 對特定的列進行缺失值刪除處理 。
dfNew = dfData.dropna(axis = 0)) # 刪除含有缺失值的行
有時也會填充缺失值或替換缺失值,在此就不做介紹了。
(2)重複資料的處理
對於重複資料,通常會刪除重複行。使用 pandas 中的 .duplicated() 可以查詢重複資料的內容,使用 .drop_duplicated() 可以刪除重複資料,也可以對指定的資料列進行去重。
dfNew = dfData.drop_duplicates(inplace=True) # 刪除重複的資料行
(3)異常值處理
資料中可能包括異常值, 是指一個樣本中的數值明顯偏離樣本集中其它樣本的觀測值,也稱為離群點。異常值可以通過箱線圖、正態分佈圖進行識別,也可以通過迴歸、聚類建模進行識別。
箱線圖技術是利用資料的分位數識別其中的異常點。箱形圖分析也超過本文的內容,不能詳細介紹了。只能籠統地說通過觀察箱形圖,可以檢視整體的異常情況,進而發現異常值。
dfData.boxplot() # 繪製箱形圖
對於異常值通常不易直接刪除,需要結合具體情況進行考慮和處理。使用 pandas 中的 .drop() 可以直接刪除異常值資料行,或者使用判斷條件來判定並刪除異常值資料行。
# 按行刪除,drop() 預設 axis=0 按行刪除
dfNew = dfData.drop(labels=0) # 按照行號 labels,刪除 行號為 0 的行
dfNew = dfData.drop(index=dfData[dfData['A']==-1].index[0]) # 按照條件檢索,刪除 dfData['A']=-1 的行
4、Python 例程(Statsmodels)
4.1 問題描述
資料檔案中收集了 30個月本公司牙膏銷售量、價格、廣告費用及同期的市場均價。
(1)分析牙膏銷售量與價格、廣告投入之間的關係,建立數學模型;
(2)估計所建立數學模型的引數,進行統計分析;
(3)利用擬合模型,預測在不同價格和廣告費用下的牙膏銷售量。
本問題及資料來自:姜啟源、謝金星,數學模型(第 3版),高等教育出版社。
需要說明的是,本文例程並不是問題最佳的求解方法和結果,只是使用該問題及資料示範讀取資料檔案和資料處理的方法。
4.2 Python 程式
# LinearRegression_v3.py
# v1.0: 呼叫 statsmodels 實現一元線性迴歸
# v2.0: 呼叫 statsmodels 實現多元線性迴歸
# v3.0: 從檔案讀取資料樣本
# 日期:2021-05-06
# Copyright 2021 YouCans, XUPT
import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
# 主程式
def main():
# 讀取資料檔案
readPath = "../data/toothpaste.csv" # 資料檔案的地址和檔名
try:
if (readPath[-4:] == ".csv"):
dfOpenFile = pd.read_csv(readPath, header=0, sep=",") # 間隔符為逗號,首行為標題行
# dfOpenFile = pd.read_csv(filePath, header=None, sep=",") # sep: 間隔符,無標題行
elif (readPath[-4:] == ".xls") or (readPath[-5:] == ".xlsx"): # sheet_name 預設為 0
dfOpenFile = pd.read_excel(readPath, header=0) # 首行為標題行
# dfOpenFile = pd.read_excel(filePath, header=None) # 無標題行
elif (readPath[-4:] == ".dat"): # sep: 間隔符,header:首行是否為標題行
dfOpenFile = pd.read_table(readPath, sep=" ", header=0) # 間隔符為空格,首行為標題行
# dfOpenFile = pd.read_table(filePath,sep=",",header=None) # 間隔符為逗號,無標題行
else:
print("不支援的檔案格式。")
print(dfOpenFile.head())
except Exception as e:
print("讀取資料檔案失敗:{}".format(str(e)))
return
# 資料預處理
dfData = dfOpenFile.dropna() # 刪除含有缺失值的資料
print(dfData.dtypes) # 檢視 df 各列的資料型別
print(dfData.shape) # 檢視 df 的行數和列數
# colNameList = dfData.columns.tolist() # 將 df 的列名轉換為列表 list
# print(colNameList) # 檢視列名列表 list
# featureCols = ['price', 'average', 'advertise', 'difference'] # 篩選列,建立自變數列名 list
# X = dfData[['price', 'average', 'advertise', 'difference']] # 根據自變數列名 list,建立 自變數資料集
# 準備建模資料:分析因變數 Y(sales) 與 自變數 x1~x4 的關係
y = dfData.sales # 根據因變數列名 list,建立 因變數資料集
x0 = np.ones(dfData.shape[0]) # 截距列 x0=[1,...1]
x1 = dfData.price # 銷售價格
x2 = dfData.average # 市場均價
x3 = dfData.advertise # 廣告費
x4 = dfData.difference # 價格差,x4 = x1 - x2
X = np.column_stack((x0,x1,x2,x3,x4)) #[x0,x1,x2,...,x4]
# 建立模型與引數估計
# Model 1:Y = b0 + b1*X1 + b2*X2 + b3*X3 + b4*X4 + e
model = sm.OLS(y, X) # 建立 OLS 模型
results = model.fit() # 返回模型擬合結果
yFit = results.fittedvalues # 模型擬合的 y 值
print(results.summary()) # 輸出迴歸分析的摘要
print("\nOLS model: Y = b0 + b1*X + ... + bm*Xm")
print('Parameters: ', results.params) # 輸出:擬合模型的係數
# 擬合結果繪圖
fig, ax = plt.subplots(figsize=(10, 8))
ax.plot(range(len(y)), y, 'bo', label='sample')
ax.plot(range(len(yFit)), yFit, 'r--', label='predict')
ax.legend(loc='best') # 顯示圖例
plt.show() # YouCans, XUPT
return
if __name__ == '__main__':
main()
4.3 程式執行結果:
period price average advertise difference sales
0 1 3.85 3.80 5.50 -0.05 7.38
1 2 3.75 4.00 6.75 0.25 8.51
2 3 3.70 4.30 7.25 0.60 9.52
3 4 3.70 3.70 5.50 0.00 7.50
4 5 3.60 3.85 7.00 0.25 9.33
OLS Regression Results
==============================================================================
Dep. Variable: sales R-squared: 0.895
Model: OLS Adj. R-squared: 0.883
Method: Least Squares F-statistic: 74.20
Date: Fri, 07 May 2021 Prob (F-statistic): 7.12e-13
Time: 11:51:52 Log-Likelihood: 3.3225
No. Observations: 30 AIC: 1.355
Df Residuals: 26 BIC: 6.960
Df Model: 3
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 8.0368 2.480 3.241 0.003 2.940 13.134
x1 -1.1184 0.398 -2.811 0.009 -1.936 -0.300
x2 0.2648 0.199 1.332 0.195 -0.144 0.674
x3 0.4927 0.125 3.938 0.001 0.236 0.750
x4 1.3832 0.288 4.798 0.000 0.791 1.976
==============================================================================
Omnibus: 0.141 Durbin-Watson: 1.762
Prob(Omnibus): 0.932 Jarque-Bera (JB): 0.030
Skew: 0.052 Prob(JB): 0.985
Kurtosis: 2.885 Cond. No. 2.68e+16
==============================================================================
OLS model: Y = b0 + b1*X + ... + bm*Xm
Parameters: const 8.036813
x1 -1.118418
x2 0.264789
x3 0.492728
x4 1.383207
版權說明:
- 1 本問題及資料來自:姜啟源、謝金星,數學模型(第 3版),高等教育出版社
- 2 本文內容及例程為作者原創,並非轉載書籍或網路內容。。
版權說明:
YouCans 原創作品
Copyright 2021 YouCans, XUPT
Crated:2021-05-06