承接上篇《Python 神兵譜之數據分析-上篇:數據採集》,今天咱們來說講這中篇:數據處理。html
若是說數據採集比如戰前情報收集、戰略部署,那麼,數據處理比如短兵相接、浴血廝殺了。俗話說,一將功成萬骨枯,戰鬥勝利後風光無限的是一軍之將,以命相博的將士每每卻默默無聞。git
數據處理也是如此,風光背後,是一位位數據處理工程師默默的付出,他們劈荊斬棘,他們乘風破浪。沒人知道他們剔除了多少髒數據,沒人知道他們變換了多少數據模型,咱們看到的只是展現給咱們的冰山一角的數據而已。github
說到數據處理,最大名鼎鼎的應該就是「Excel」了,它的大名,可謂無人不知,無人不曉。有了 Excel,即便毫無編程經驗的人,都能對數據耍上兩把。而咱們今天就來看看,僅僅一點點代碼,就能實現的更爲強大的功能。算法
第一把交椅,必須是「Numpy」了。很多人可能據說過,可是可能從未用過,由於 Numpy 是 Python 數據處理的基石,是其餘很多相關工具的依賴。編程
Numpy 的功能很是純粹,它爲 Python 提供了一個很是強大且靈活的「數組」數據結構。api
可是 Python 不是有列表(list)了嗎?爲何還要其餘的「數組」結構?數組
Numpy 主要有如下幾個特色:bash
Numpy 提供了很是方便的方法生成多維數組,例如從 list 轉換而來。數據結構
import numpy as np
a = np.array([1,2,3,4])
複製代碼
第一行引入 Numpy,這是通常推薦的作法,用 as 別名爲 np。不是必須的,但建議遵循。app
還有衆多的生成函數。
# 生成一個 3 * 4 的矩陣,每一個元素都是 0
np.zeros((3,4))
# 生成一個 2 * 3 的矩陣,每一個元素都是 1
np.ones( (2,3) )
# 等差數列生成,從 10 到 30,5 遞增
np.arange(10, 30, 5)
複製代碼
不一樣於 list,數組的每一個元素必須有一致的數據類型。
>>> a.dtype.name
'int64'
複製代碼
能夠在建立時經過 dtype 參數指定,例如 int32,int64,float64 等。
Numpy 的數組有幾個比較重要的屬性。
# 建立一個 1 到 14 到數組,並改爲 3 * 5 的矩陣
>>> a = np.arange(15).reshape(3, 5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> a.ndim
2
>>> a.shape
(3, 5)
>>> a.size
15
>>> a.dtype.name
'int64'
>>> a.itemsize
8
複製代碼
這仍是牛刀小試,讓咱們來見識 Numpy 的實力吧,像操做普通標量同樣操做數組。
# 數組每一個元素乘以 2
>>> b = a * 2
>>> b
array([[ 0, 2, 4, 6, 8],
[10, 12, 14, 16, 18],
[20, 22, 24, 26, 28]])
# 數組對應元素相加
>>> a + b
array([[ 0, 3, 6, 9, 12],
[15, 18, 21, 24, 27],
[30, 33, 36, 39, 42]])
# 數組對應元素相乘
>>> a * b
array([[ 0, 2, 8, 18, 32],
[ 50, 72, 98, 128, 162],
[200, 242, 288, 338, 392]])
# 邏輯判斷,每一個元素是否小於 8
>>> a < 8
array([[ True, True, True, True, True],
[ True, True, True, False, False],
[False, False, False, False, False]], dtype=bool)
複製代碼
基本的函數操做
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
# 縱向求和(軸索引爲 0)
>>> a.sum(axis=0)
array([15, 18, 21, 24, 27])
# 橫向求和(軸索引爲 1)
>>> a.sum(axis=1)
array([10, 35, 60])
# 每行的最小值(軸索引爲 1)
>>> a.min(axis=1)
array([ 0, 5, 10])
複製代碼
取數據
# 取索引 0,0 處的元素,也就是第一行第一個
>>> a[0,0]
0
# 取索引 2,3 處的元素
>>> a[2,3]
13
複製代碼
固然也能夠切片操做
# 取索引爲 1 到 2 (不含)的行,也就是第 2 行
>>> a[1:2]
array([[5, 6, 7, 8, 9]])
# 取索引爲 1 到 3 (不含)的行,索引爲 2 到 5(不含)的列
>>> a[1:3,2:5]
array([[ 7, 8, 9],
[12, 13, 14]]))
複製代碼
還有其餘的數組轉換、線性代數計算等函數,就不詳細展開了。Numpy 就是咱們進行數據處理的基本容器,有了 Numpy 提供的數組結構,後面的操做就遊刃有餘了。
Scipy 是數學、工程、科學計算相關的函數庫,自己是基於 Numpy 的數組的,也是和 Numpy 師出同門。
Scipy 有許多子模塊,每一個子模塊提供各個領域特定的功能。
各個函數的使用須要必定的理論基礎,scipy 已經幫助咱們實現,只須要調用便可。
例如,咱們計算以下的積分方程
>>> import scipy.integrate as integrate
>>> import scipy.special as special
>>> result = integrate.quad(lambda x: special.jv(2.5,x), 0, 4.5)
>>> result
(1.1178179380783249, 7.8663172481899801e-09)
複製代碼
是否是不再怕高數做業了?
Pandas 不是一隻普通的熊貓。Pandas 是基於 Numpy 的高級的數據處理工具庫。Pandas 最擅長的就是處理表格數據,也就是咱們熟悉的 Excel 類型的數據,Pandas 提供的方法能讓咱們簡單的幾行代碼快速處理類 Excel 或者關係型數據表的數據。
一個最簡單的例子。
>>> import pandas as pd # 和 nunpy 同樣的約定,通常引入後別名爲 pd
>>> df = pd.read_csv('test.csv') # 讀取 csv 文件
>>> df # 顯示讀取的內容,爲兩列三行的數據
name price
0 apple 5
1 banana 3
2 pear 2
>>> df.describe() # 查看數據統計,自動找出數據列(price),計算相關統計量
price
count 3.000000
mean 3.333333
std 1.527525
min 2.000000
25% 2.500000
50% 3.000000
75% 4.000000
max 5.000000
>>> df.price = df.price * 2 # 全部價格都乘以 2
>>> df
name price
0 apple 10
1 banana 6
2 pear 4
>>> df.to_csv('out.csv', index=False) # 導出數據到 csv 文件
複製代碼
Pandas 能夠用來作數據清洗、轉換、聚合等操做,爲下一步數據可視化及機器學習準備數據。
Pandas 有多種數據類型,其中就常見的兩種就是 Series 和 DataFrame。
DataFrame 能夠理解爲一個數據表格,行有行的標籤(索引),列有列的標籤(索引),是否是和 Excel 很像?
而 Series 便是這個數據表格的一列或者一行。因此一個 DataFrame 也可看做是一個 Series 數組。
Pandas 提供了一系列的方法快速的從其餘數據源導入導出數據。
Pandas 也能很是方便的「挑選」特定的數據。
經過 Matplotlib 庫,Pandas 能夠方便的繪製可視化圖表。
對於基本的數據抽取、轉換、清洗等工做,Pandas 徹底能勝任,掌握了 Pandas 就有了應對各類敵人的百變戰甲。
Scikit-Learn 是 Python 的機器學習庫,也是在 Numpy 和 Scipy 的基礎上,提供了強大的機器學習算法的實現。例如分類算法(SVM,K 近鄰,隨機森林等),迴歸算法(線性迴歸、SVR 等),聚類算法(K-means、譜聚類等)、降維、模型選擇、數據預處理等等。
Scikit-Learn 經過對算法的高度抽象,對於一個基本的算法調用過程,基本上就簡化爲了:初始化->數據預處理->訓練->預測,流程中的幾個步驟。
一個簡單的線性迴歸的例子。
>>> from sklearn import linear_model
>>> reg = linear_model.LinearRegression()
>>> reg.fit([[0, 0], [1, 1], [2, 2]], [0, 1, 2])
LinearRegression()
>>> reg.coef_
array([0.5, 0.5])
複製代碼
除了基本的算法實現,scikit-learn 提供的數據預處理也極其強大,基本能涵蓋數據預處理的許多方面。
例如,數據歸一化,快速的 Z-score 歸一化,使數據知足正態分佈。
>>> from sklearn import preprocessing
>>> import numpy as np
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
>>> X_scaled = preprocessing.scale(X_train)
>>> X_scaled
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
複製代碼
數據編碼,能夠將枚舉的字符串數據編碼爲數值型,方便後續計算。
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OrdinalEncoder()
>>> enc.transform([['female', 'from US', 'uses Safari']])
array([[0., 1., 1.]])
複製代碼
One Hot 編碼,將枚舉字符串數據轉換爲多列的布爾數據(0 / 1)。
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder()
>>> enc.transform([['female', 'from US', 'uses Safari'],
... ['male', 'from Europe', 'uses Safari']]).toarray()
array([[1., 0., 0., 1., 0., 1.],
[0., 1., 1., 0., 0., 1.]])
複製代碼
缺失值處理。
>>> import numpy as np
>>> from sklearn.impute import SimpleImputer
>>> imp = SimpleImputer(missing_values=np.nan, strategy='mean')
>>> imp.fit([[1, 2], [np.nan, 3], [7, 6]])
SimpleImputer()
>>> X = [[np.nan, 2], [6, np.nan], [7, 6]]
>>> print(imp.transform(X))
[[4. 2. ]
[6. 3.666...]
[7. 6. ]]
複製代碼
若是想要看一個實戰的項目,這裏有一個基因型預測身高的項目例子。該項目根據用戶在多個基因位點的基因型和身高數據進行模型訓練,而後可根據訓練的模型預測其餘用戶的身高。咱們先無論這個預測的理論可行性和準確性,不過整個數據預處理和模型訓練的操做是一個學習 scikit-learn 的過程。
statsmodels 是一個 Python 的統計模型庫,提供了不少統計相關的函數和操做,例如線性迴歸、統計檢驗、時間序列分析等。statsmodels 也是構建在 Numpy、SciPy 和 Pandas 之上的。
線性迴歸模型
import statsmodels.api as sm
data = sm.datasets.scotland.load(as_pandas=False) # 載入測試數據
data.exog = sm.add_constant(data.exog)
# 實例化伽馬模型
>>> gamma_model = sm.GLM(data.endog, data.exog, family=sm.families.Gamma())
>>> gamma_results = gamma_model.fit()
>>> print(gamma_results.summary())
Generalized Linear Model Regression Results
==============================================================================
Dep. Variable: y No. Observations: 32
Model: GLM Df Residuals: 24
Model Family: Gamma Df Model: 7
Link Function: inverse_power Scale: 0.0035843
Method: IRLS Log-Likelihood: -83.017
Date: Fri, 21 Feb 2020 Deviance: 0.087389
Time: 13:59:13 Pearson chi2: 0.0860
No. Iterations: 6
Covariance Type: nonrobust
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
const -0.0178 0.011 -1.548 0.122 -0.040 0.005
x1 4.962e-05 1.62e-05 3.060 0.002 1.78e-05 8.14e-05
x2 0.0020 0.001 3.824 0.000 0.001 0.003
x3 -7.181e-05 2.71e-05 -2.648 0.008 -0.000 -1.87e-05
x4 0.0001 4.06e-05 2.757 0.006 3.23e-05 0.000
x5 -1.468e-07 1.24e-07 -1.187 0.235 -3.89e-07 9.56e-08
x6 -0.0005 0.000 -2.159 0.031 -0.001 -4.78e-05
x7 -2.427e-06 7.46e-07 -3.253 0.001 -3.89e-06 -9.65e-07
==============================================================================
複製代碼
方差分析
>>> import statsmodels.api as sm
>>> from statsmodels.formula.api import ols
>>> moore = sm.datasets.get_rdataset("Moore", "carData", cache=True) # 載入測試數據
>>> data = moore.data
>>> data = data.rename(columns={"partner.status": "partner_status"}) # 重命名
>>> moore_lm = ols('conformity ~ C(fcategory, Sum)*C(partner_status, Sum)', data=data).fit()
>>> table = sm.stats.anova_lm(moore_lm, typ=2) # Type 2 ANOVA DataFrame
>>> print(table)
sum_sq df F PR(>F)
C(fcategory, Sum) 11.614700 2.0 0.276958 0.759564
C(partner_status, Sum) 212.213778 1.0 10.120692 0.002874
C(fcategory, Sum):C(partner_status, Sum) 175.488928 2.0 4.184623 0.022572
Residual 817.763961 39.0 NaN NaN
複製代碼
XGBoost 是一個改進的梯度加強算法(gradient boosting),基本的梯度加強算法(GBDT)已經在 scikit-learn 中有了實現。而 XGBoost 改進了該算法,提供了分佈式的能力,更快速,更靈活,更便攜。因爲 XGBoost 的簡單易學,性能高效和表現優異,經常被用於各類數據科學算法大賽。例如,著名的 Kaggle 大賽,XGBoost 是許多競賽的奪冠熱門算法。
XGBoost 是一個算法的名稱,可是提供衆多語言的實現,例如 Python, R, Java, Scala, C++ 等,同時也支持 Hadoop,Spark 等大數據生態。
若是須要詳細瞭解 GBDT 和 XGBoost 的前世此生,能夠戳這篇文章。
這裏還有幾個 Kaggle 競賽項目的具體例子,能夠供你們直接學習。
固然,數據處理的方式和算法實在是太多了,各類優化的算法庫也是層出不窮,還有很多 BI 軟件和商業化的工具。這裏展現的幾個算是這個領域中最大名鼎鼎的幾件大殺器,大殺器在手,蝦兵蟹將繞着走!
百媚生 Python《神兵譜》之數據分析-中篇,若是以爲有用,請點贊關注收藏哦!