承接上篇《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《神兵谱》之数据分析-中篇,若是以为有用,请点赞关注收藏哦!