本文内容整理自DataCamp课程之 Intro to Python for Data Science.
本系列将包括以下内容:
- Python 基础
- Python 列表 list
- 函数、方法和包
- Numpy 入门 (本文)
访问 我的github 可下载本文对应的notebook以及练习答案,便于亲手实践。
注意:本文代码基于Python3版本。如果要在python2中执行,需要先导入_future_模块。
#仅在Python2中使用
#from __future__ import division
#from __future__ import print_function
1. 一维数组
我们在第2讲提到的列表(list)具有非常强大的功能,但却不能很好满足数据分析的要求:实现高速且大量的数学运算。
用列表分别记录身高和体重这两组数据,我们尝试一下是否能用它来直接计算BMI指数。
height = [1.73, 1.68, 1.71, 1.89, 1.79] #身高列表
weight = [65.4, 59.2, 63.6, 88.4, 68.7] #体重列表
bmi = weight / height ** 2 #计算BMI指数
bmi
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-b6ce7d301f86> in <module>()
1 height = [1.73, 1.68, 1.71, 1.89, 1.79] #身高列表
2 weight = [65.4, 59.2, 63.6, 88.4, 68.7] #体重列表
----> 3 bmi = weight / height ** 2 #计算BMI指数
4 bmi
TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'
以上错误告诉我们,列表不能实现整体的数学运算,这正是它的局限。那么该如何有效解决呢?
Python 中有专门的数值计算基础包 Numpy,它是 Numeric Python 的缩写。Numpy提供的数组(array)可以很好地替代 Python 列表,不仅可以实现整体运算,而且还非常简单快速。
那么就让我们用 Numpy 数组来实现上面列表无法完成的BMI指数计算吧。
import numpy as np #导入numpy 包
np_height = np.array(height) #创建身高的numpy数组
np_height
array([ 1.73, 1.68, 1.71, 1.89, 1.79])
np_weight = np.array(weight) #创建体重的numpy数组
np_weight
array([ 65.4, 59.2, 63.6, 88.4, 68.7])
bmi = np_weight / np_height ** 2 #计算BMI指数
bmi
array([ 21.85171573, 20.97505669, 21.75028214, 24.7473475 , 21.44127836])
列表元素可以是任何类型,但是 Numpy 数组元素必须是相同类型。下面的例子说明,如果使用了不同的数据类型,则会被强制转化成同一种。
np.array([1.0, "is", True])
array(['1.0', 'is', 'True'], dtype='<U32')
加号 +
在列表和 Numpy 数组中的作用也是不一样的。在列表中,加号实现列表的拼接;而在 Numpy 数组中,加号则是进行对应元素的加法运算。
python_list = [1, 2, 3]
python_list + python_list
[1, 2, 3, 1, 2, 3]
numpy_array = np.array([1, 2, 3])
numpy_array + numpy_array
array([2, 4, 6])
切片操作,Numpy 数组与 Python 列表类似。
bmi[1]
20.975056689342409
bmi[1:4]
array([ 20.97505669, 21.75028214, 24.7473475 ])
但 Numpy 数组能做的远不止这些,比如要找到bmi大于23的数,该怎么做呢?
bmi > 23
array([False, False, False, True, False], dtype=bool)
首先我们得到一个布尔变量组成的数组,然后试着将它放入bmi[ ]中会有什么效果?
bmi[bmi > 23]
array([ 24.7473475])
于是我们得到了想要的结果,可见,Numpy 数组是多么强大呀!
练习4-1:
你的第一个 Numpy 数组:棒球运动员的身高数据。
# 创建棒球运动员的身高列表 baseball
baseball = [180, 215, 210, 210, 188, 176, 209, 200]
# 导入numpy包
# 用列表baseball创建numpy数组:np_baseball
# 打印np_baseball的数据类型
# 将以厘米为单位的身高转换成以米为单位
# 找出高于2米的运动员身高数据
# 打印输出最后一个棒球运动员的身高
# 打印输出最后两个运动员的身高
2. 二维数组
Numpy 数组不仅限于一维,也可以是多维的。比如创建一个身高、体重的二维数组。
np_2d = np.array([[1.73, 1.68, 1.71, 1.89, 1.79],
[65.4, 59.2, 63.6, 88.4, 68.7]])
np_2d
array([[ 1.73, 1.68, 1.71, 1.89, 1.79], [ 65.4 , 59.2 , 63.6 , 88.4 , 68.7 ]])
np_2d.shape
(2, 5)
这是一个2行、5列的二维数组,第一行代表身高,第二行代表体重。索引结构如下图所示:
了解了索引的结构,就可以进行切片操作了。
np_2d[0] #选取第1行
array([ 1.73, 1.68, 1.71, 1.89, 1.79])
np_2d[0][2] #选取第1行第3列
1.71
np_2d[0,2] #选取第1行第3列的另一种方法
1.71
np_2d[:,1:3] #选取每一行的第2、3列
array([[ 1.68, 1.71], [ 59.2 , 63.6 ]])
np_2d[1,:] #选取第2行的所有列
array([ 65.4, 59.2, 63.6, 88.4, 68.7])
另外,二维数组的运算也很有意思,仔细观察下面的示例。
np_mat = np.array([[1, 2],
[3, 4],
[5, 6]])
np_mat * 2
array([[ 2, 4], [ 6, 8], [10, 12]])
np_mat + np.array([10, 10])
array([[11, 12], [13, 14], [15, 16]])
np_mat + np_mat
array([[ 2, 4], [ 6, 8], [10, 12]])
练习4-2:
你的第一个 Numpy 二维数组:棒球运动员的身高、体重数据。
# 创建二维列表 baseball, 第一列是身高,第二列是体重
baseball = [[180, 78.4],
[215, 102.7],
[210, 98.5],
[188, 75.2]]
#导入 numpy 基础包
# 用二维列表baseball创建二维数组 np_baseball
# 打印输出 np_baseball 的类型
# 打印输出 np_baseball的shape属性
# 打印输出第3行的数据
# 打印输出第二列体总数据
# 打印输出第4名运动员的身高
3. 基础统计
分析的第一步,是观察了解数据。对于少量数据,也许看一眼就行了,但是对于大量数据,就需要用到统计的知识了。Numpy 中有非常丰富的统计工具,那就让我们一起来看看吧。
下面的例子中,我们收集到棒球运动员的一组数据,每一行代表一位选手的数据,每一列所代表的是体重、身高、年龄信息。
sample = np.array([
[ 74. , 215. , 34.69],
[ 72. , 210. , 30.78],
[ 72. , 210. , 35.43],
[ 73. , 188. , 35.71],
[ 69. , 176. , 29.39],
[ 69. , 209. , 30.77],
[ 71. , 200. , 35.07],
[ 76. , 231. , 30.19],
[ 71. , 180. , 27.05],
[ 73. , 188. , 23.88],
[ 73. , 180. , 26.96],
[ 74. , 185. , 23.29],
[ 74. , 160. , 26.11],
[ 69. , 180. , 27.55],
[ 70. , 185. , 34.27],
[ 73. , 189. , 27.99],
[ 75. , 185. , 22.38],
[ 78. , 219. , 22.89],
[ 79. , 230. , 25.76],
[ 76. , 205. , 36.33]])
首先,用切片的方法得到运动员的身高数据。
height = sample[:,1]
height
array([ 215., 210., 210., 188., 176., 209., 200., 231., 180., 188., 180., 185., 160., 180., 185., 189., 185., 219., 230., 205.])
使用 np.mean()
函数计算身高的平均值:
np.mean(height)
196.25
使用 np.median()
函数计算身高的中位数:
np.median(height)
188.5
使用 np.std()
函数计算身高的标准差:
np.std(height)
18.616860637604827
使用 np.corrcoef()
函数计算体重和身高的相关系数:
np.corrcoef(sample[:,0], sample[:,1])
array([[ 1. , 0.50671793], [ 0.50671793, 1. ]])
使用 Numpy 还可以进行统计模拟,生成随机数或符合特定分布的数值。比如,下面的代码生成了一组100个符合正态分布的数值,均值是1.75,标准差是0.2。
data = np.round(np.random.normal(1.75, 0.20, size=100), 2)
像 sum()
、sort()
这类的函数,Numpy 和 Python 中都有,那么它们的区别在哪里呢?关键在于 Numpy 中的计算速度更快,因为 Numpy 是专门针对数值计算的,而 Python 还要考虑其他数据类型。
sum(height)
3925.0
np.sum(height)
3925.0
练习4-3:
综合练习:找出足球运动中守门员和其他运动员的身高的中位数。
# 创建足球运动员的位置和对应的身高数据
positions = ['GK', 'M', 'A', 'D', 'M', 'D', 'M', 'M', 'M', 'A', 'M', 'M', 'A', 'A', 'A', 'M', 'D', 'A', 'D', 'M', 'GK', 'D', 'D', 'M', 'M', 'M', 'M', 'D', 'M', 'GK']
heights = [191, 184, 185, 180, 181, 187, 170, 179, 183, 186, 185, 170, 187, 183, 173, 188, 183, 180, 188, 175, 193, 180, 185, 170, 183, 173, 185, 185, 168, 190]
# 导入numpy包
import numpy as np
# 将列表 positions 和 heights 分别转化成numpy数组: np_positions, np_heights
# 将守门员的身高数据存入变量 gk_heights, 守门员对应的位置编码是’GK‘
gk_heights =
# 将守门员之外的其他运动员的身高数据存入变量 other_heights
other_heights =
# 打印输出守门员身高的中位数,替换代码中的'None'
print("Median height of goalkeepers: " + str(None))
# 打印输出其他运动员身高的中位数,替换代码中的'None'
print("Median height of other players: " + str(None))
补充:
关于 我的github 中文件下载的方式:
如果下载单个文件,点击所要下载的文件,在新打开的页面中找到右上方的
raw
按钮,右击另存为即可。另外文件名需要删除后缀 .txt,而保留原始格式后缀,如 .ipynb 。如果打包下载,回到github库的根目录中,点击右上方绿色的
Clone and download
按钮,选择Download ZIP
即可。
本文使用Jupyter notebook 编写,关于它的说明和安装方法,可以参考我之前的两篇文章。