Python数据分析的起手式(4)Numpy入门

96
鱼心DrFish
2017.03.15 14:16* 字数 1583

本文内容整理自DataCamp课程之 Intro to Python for Data Science.

本系列将包括以下内容:

访问 我的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列的二维数组,第一行代表身高,第二行代表体重。索引结构如下图所示:

Numpy 数组

了解了索引的结构,就可以进行切片操作了。

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 编写,关于它的说明和安装方法,可以参考我之前的两篇文章。

数据分析实践之路