导读:NumPy(Numerical Python的简称)是高性能科学计算和数据分析的基础包,提供了矩阵运算的功能。
在处理自然语言过程中,需要将文字(中文或其他语言)转换为向量。即把对文本内容的处理简化为向量空间中的向量运算。基于向量运算,我们就可以实现文本语义相似度、特征提取、情感分析、文本分类等功能。
作者:涂铭,刘祥,刘树春
NumPy提供了以下几个主要功能:
- ndarray——一个具有向量算术运算和复杂广播能力的多维数组对象。
- 用于对数组数据进行快速运算的标准数学函数。
- 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。
- 非常有用的线性代数,傅里叶变换和随机数操作。
- 用于集成C /C++和Fortran代码的工具。
除明显的科学用途之外,NumPy也可以用作通用数据的高效多维容器,可以定义任意的数据类型。这些使得NumPy能无缝、快速地与各种数据库集成。
提示:这里提到的“广播”可以这么理解:当有两个维度不同的数组(array)运算的时候,可以用低维的数组复制成高维数组参与运算(因为NumPy运算的时候需要结构相同)。
本文NumPy的要点包括:
- 创建NumPy数组
- 获取NumPy中数组的维度
- NumPy数组索引与切片
- NumPy数组比较
- 替代值
- NumPy数据类型转换
- NumPy的统计计算方法
01 创建数组
在NumPy中,最核心的数据结构是ndarray,ndarray代表的是多维数组,数组指的是数据的集合。为了方便理解,我们来举一个小例子。
1. 一个班级里学生的学号可以通过一维数组来表示:数组名叫a,在a中存储的是数值类型的数据,分别是1,2,3,4。
索引 | 学号 |
---|---|
0 | 1 |
1 | 2 |
2 | 3 |
3 | 4 |
其中a[0]代表的是第一个学生的学号1,a[1]代表的是第二个学生的学号2,以此类推。
2. 一个班级里学生的学号和姓名,则可以用二维数组来表示:数组名叫b
1 | Tim |
---|---|
2 | Joey |
3 | Johnny |
4 | Frank |
类似的,其中b[0,0]代表的就是1(学号),b[0,1]代表的就是Tim(学号为1的学生的名字),以此类推b[1,0]代表的是2(学号)等。
借用线性代数的说法,一维数组通常称为向量(vector),二维数组通常称为矩阵(matrix)。
当我们安装完Anaconda之后,默认情况下NumPy已经在库中了,所以不需要额外安装。我们来写一些语句简单测试下NumPy:
1)在Anaconda中输入,如果没有报错,那么说明NumPy是正常工作的。
In [1]: import numpy as np
稍微解释下这句语句:通过import关键字将NumPy库引入,然后通过as为其取一个别名np,别名的作用是为了之后写代码的时候方便引用。
2)通过NumPy中的array(),可以将向量直接导入:
vector = np.array([1,2,3,4])
3)通过numpy.array()方法,也可以将矩阵导入:
matrix = np.array([[1,'Tim'],[2,'Joey'],[3,'Johnny'],[4,'Frank']])
02 获取NumPy中数组的维度
首先我们通过NumPy中的一个方法arange(n),生成0到n-1的数组。比如我们输入np.arange(15),可以看到返回的结果是array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])。
之后再通过NumPy中的reshape(row,column)方法,自动构架一个多行多列的array对象。
比如我们输入:
a = np.arange(15).reshape(3,5) #代表3行5列
可以看到结果:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
我们有了基本数据之后,可以通过NumPy提供的shape属性获取NumPy数组的维度。
print(a.shape)
可以看到返回的结果,这个是一个元组(tuple),第一个3代表的是3行,第二个5代表的是5列:
(3, 5)
03 获取本地数据
我们可以通过NumPy中genfromtxt()方法来读取本地的数据集。需要使用的数据集,house-prices.csv是由逗号(,)分隔的,在Github的data目录下能下载到。我们可以使用以下语句来读取这个数据集:
import numpy as np
nfl = np.genfromtxt("D:/numpy/data/price.csv", delimiter=",")
print(nfl)
上述代码从本地读取price.csv文件到NumPy数组对象中(ndarray),我们看一下数据集的前几行。
[[ nan nan nan nan
nan nan]
[ 1.00000000e+00 1.14300000e+05 2.00000000e+00 2.00000000e+00
nan nan]
[ 2.00000000e+00 1.14200000e+05 4.00000000e+00 2.00000000e+00
nan nan]
[ 3.00000000e+00 1.14800000e+05 3.00000000e+00 2.00000000e+00
nan nan]
[ 4.00000000e+00 9.47000000e+04 3.00000000e+00 2.00000000e+00
nan nan]
暂时先不用考虑返回数据中出现的nan。
每一行的数据代表了房间的地区,是否是砖瓦结构,有多少卧室、洗手间以及价格的描述。
每个列代表了:
- Home:房子的id
- Price:房子的价格
- Bedrooms:有多少个卧室
- Bathroom:有多少个洗手间
- Brick:是否是砖房
- Neighborhood:地区
注意:NumPy数组中的数据必须是相同类型,比如布尔类型(bool)、整型(int),浮点型(float)以及字符串类型(string)。NumPy可以自动判断数组内的对象类型,我们可以通过NumPy数组提供的dtype属性来获取类型。
04 正确读取数据
回到之前的话题,上文发现显示出来的数据里面有数据类型na(not available)和nan(not a number),前者表示读取的数值是空的、不存在的,后者是因为数据类型转换出错。对于nan的出错,我们可以用genfromtxt()来转化数据类型。
- dtype关键字要设定为‘U75’.表示每个值都是75byte的unicode。
- skip_header关键字可以设置为整数,这个参数可以跳过文件开头的对应的行数,然后再执行任何其他操作。
import numpy as np
nfl = np.genfromtxt("d:/numpy/data/price.csv", dtype='U75', skip_header = 1,delimiter=",")
print(nfl)
05 NumPy数组索引
NumPy支持list一样的定位操作。举例来说:
import numpy as np
matrix = np.array([[1,2,3],[20,30,40]])
print(matrix[0,1])
得到的结果是2。
上述代码中的matrix[0,1],其中0代表的是行,在NumPy中0代表起始第一个,所以取的是第一行,之后的1代表的是列,所以取的是第二列。那么最后第一行第二列就是2这个值了。
06 切片
NumPy支持list一样的切片操作。
import numpy as np
matrix = np.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
print(matrix[:,1])
print(matrix[:,0:2])
print(matrix[1:3,:])
print(matrix[1:3,0:2])
上述的print(matrix[:,1])语法代表选择所有的行,但是列的索引是1的数据。那么就返回10,25,40。
print(matrix[:,0:2])代表的是选取所有的行,列的索引是0和1。
print(matrix[1:3,:])代表的是选取行的索引值1和2以及所有的列。
print(matrix[1:3,0:2])代表的是选取行的索引1和2以及列的索引是0和1的所有数据。
07 数组比较
NumPy强大的地方是数组或矩阵的比较,数据比较之后会产生boolean值。
举例来说:
import numpy as np
matrix = np.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
m = (matrix == 25)
print(m)
我们看到输出的结果为:
[[False False False]
[False True False]
[False False False]]
我们再来看一个比较复杂的例子:
import numpy as np
matrix = np.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
second_column_25 = (matrix[:,1] == 25)
print(second_column_25)
print(matrix[second_column_25, :])
上述代码中print(second_column_25)输出的是[False True False],首先matrix[:,1]代表的是所有的行,以及索引为1的列->[10,25,40],最后和25进行比较,得到的就是false,true,false。print(matrix[second_column_25, :])代表的是返回true值的那一行数据-> [20,25,30]。
注意:上述的例子是单个条件,NumPy也允许我们使用条件符来拼接多个条件,其中“&”代表的是“且”,“|”代表的是“或”。比如vector=np.array([5,10,11,12]),equal_to_five_and_ten =(vector == 5) & (vector == 10)返回的都是false,如果是equal_to_five_or_ten =(vector == 5)|(vector == 10)返回的是[True,True,False,False]
08 替代值
NumPy可以运用布尔值来替换值。
在数组中:
vector = numpy.array([5, 10, 15, 20])
equal_to_ten_or_five = (vector == 10) | (vector == 5)
vector[equal_to_ten_or_five] = 50
print(vector)
[50, 50, 15, 20]
在矩阵中:
matrix = numpy.array([
[5, 10, 15],
[20, 25, 30],
[35, 40, 45]
])
second_column_25 = matrix[:,1] == 25
matrix[second_column_25, 1] = 10
print(matrix)
[[ 5 10 15]
[20 10 30]
[35 40 45]]
我们先创立数组matrix。将matrix的第二列和25比较,得到一个布尔值数组。second_column_25将matrix第二列值为25的替换为10。
替换有一个很棒的应用之处,就是替换那些空值。之前提到过NumPy中只能有一个数据类型。我们现在读取一个字符矩阵,其中有一个值为空值。其中的空值我们很有必要把它替换成其他值,比如数据的平均值或者直接把他们删除。这在大数据处理中很有必要。这里,我们演示把空值替换为“0”的操作。
import numpy as np
matrix = np.array([
['5', '10', '15'],
['20', '25', '30'],
['35', '40','' ]
])
second_column_25 = (matrix[:,2] == '')
matrix[second_column_25, 2]='0'
print(matrix)
09 数据类型转换
NumPy ndarray数据类型可以通过参数dtype 设定,而且可以使用astype转换类型,在处理文件时这个会很实用,注意astype 调用会返回一个新的数组,也就是原始数据的一份复制。
比如,把String转换成float。如下:
vector = numpy.array(["1", "2", "3"])
vector = vector.astype(float)
注意:上述例子中,如果字符串中包含非数字类型的时候,从string转float就会报错。
10 NumPy的统计计算方法
NumPy内置很多计算方法。其中最重要的统计方法有:
- sum():计算数组元素的和;对于矩阵计算结果为一个一维数组,需要指定行或者列。
- mean():计算数组元素的平均值;对于矩阵计算结果为一个一维数组,需要指定行或者列。
- max():计算数组元素的最大值;对于矩阵计算结果为一个一维数组,需要指定行或者列。
需要注意的是,用于这些统计方法计算的数值类型必须是int或者float。
数组例子:
vector = numpy.array([5, 10, 15, 20])
vector.sum()
#得到的结果是50
矩阵例子:
matrix=
array([[ 5, 10, 15],
[20, 10, 30],
[35, 40, 45]])
matrix.sum(axis=1)
array([ 30, 60, 120])
matrix.sum(axis=0)
array([60, 60, 90])
如上述例子所示,axis = 1计算的是行的和,结果以列的形式展示。axis = 0计算的是列的和,结果以行的形式展示。