NumPy,全称是 Numerical Python,它是目前 Python 数值计算中最重要的基础模块。NumPy 是针对多维数组的一个科学计算模块,这个模块封装了很多数组类型的常用操作。
使用numpy来创建数组
import numpy as np
data = np.array([1, 2, 3])
print(data)
# 输出:[1 2 3]
print(type(data))
# 输出:<class 'numpy.ndarray'>
除了使用
np.array()
方法来创建一个多维数组,numpy 还提供了两个实用的方法——np.ones()
和np.zeros(),
分别生成元素全为 1 和 0 的多维数组。
ones = np.ones(3)
print(ones)
# 输出:[1. 1. 1.]
zeros = np.zeros(3)
print(zeros)
# 输出:[0. 0. 0.]
np.ones()
和np.zeros()
的参数用于指定生成的多维数组里有多少个元素。- 并且生成出来的不是 1 和 0,而是 1. 和 0.。这是因为默认生成的是浮点数,numpy 会省略小数点后的 0,因此 1.0 和 0.0 变成了 1. 和 0.。
如果想要生成整数的话,可以传入 dtype
参数来指定类型:
ones = np.ones(3, dtype='int')
print(ones)
# 输出:[1 1 1]
zeros = np.zeros(3, dtype='int')
print(zeros)
# 输出:[0 0 0]
数组的加减乘除:
列表间只有加法操作,作用是将两个列表的元素合并在一起。而多维数组间可以进行加减乘除的四则运算,运算规则也很简单:将两个数组中对应位置的元素一一进行运算。
两个多维数组的形状必须一致才能进行四则运算
data = np.array([1, 2])
ones = np.ones(2)
print(data + ones)
# 输出:[2. 3.]
除了多维数组间的四则运算,多维数组直接和数字进行计算的方式也很常用
data = np.array([1, 2])
print(data + 1)
# 输出:[2 3]
上述效果用列表来实现也是可以的
data = []
for i in [1, 2]:
data.append(i + 1)
print(data)
# 输出:[2, 3]
用列表就必须用到循环,而 numpy 中这种不用编写循环就可以对数据进行批量运算的方式叫做 矢量化。numpy 中的矢量化操作把内部循环委托给高度优化的 C 和 Fortran 函数,从而实现更清晰,更快速的 Python 代码。
多维数组:
一维数组只有行,二维数组相比一维数组多了列这个维度,而三维数组则类似多个二维数组堆叠在一起,形如一个立方体。
将单层嵌套列表传入 np.array()
方法创建一个二维数组:
# 单层嵌套列表
nested_list = [[1, 2], [3, 4]]
print(nested_list)
# 输出:[[1, 2], [3, 4]]
# 二维数组
data = np.array(nested_list)
print(data)
# 输出:
# [[1 2]
# [3 4]]
通过嵌套列表创建的二维数组也是用空格分隔的,并且分成了两行。列表中的第一个元素
[1, 2]
在第一行,第二个元素[3, 4]
在第二行。
ones()
和 zeros()
方法同样也能快速创建元素全为 1 和 0 的二维数组。
创建二维数组要传入一个包含行和列信息的元组。比如:np.ones((m, n))
表示创建一个 m 行 n 列且元素全为 1 的二维数组。
ones = np.ones((3, 2))
print(ones)
# 输出:
# [[1. 1.]
# [1. 1.]
# [1. 1.]]
zeros = np.zeros((3, 2))
print(zeros)
# 输出:
# [[0. 0.]
# [0. 0.]
# [0. 0.]]
多维数组的属性:
ndim
:多维数组维度的个数。例如:二维数组的ndim
为 2;shape
:多维数组的形状。它是一个元组,每个元素分别表示每个维度中数组的长度。对于 m 行和 n 列的的数组,它的shape
将是(m, n)
。因此,shape
元组的长度(元素个数)就是ndim
的值;size
:多维数组中所有元素的个数。shape
元组中每个元素的乘积就是size
的值;dtype
:多维数组中元素的类型。
data = np.array([[1, 2, 3], [4, 5, 6]])
print('ndim:', data.ndim)
print('shape:', data.shape)
print('size:', data.size)
print('dtype:', data.dtype)
# 输出:
# ndim: 2
# shape: (2, 3)
# size: 6
# dtype: int64
int64 是 numpy 提供的类型,表示 64 位的整数。
二维数组的通用方法:
通过 axis
参数可以指定计算方向
data = np.array([[1, 2], [5, 3], [4, 6]])
# 不指定 axis
print(data.max())
# 输出:6
# axis=0
print(data.max(axis=0))
# 输出:[5 6]
# axis=1
print(data.max(axis=1))
# 输出:[2 5 6]
二维数组的索引和分片:
- 二维数组的索引和分片同样和一维数组类似,只是在行索引的基础上再加上列索引。形如
data[m, n]
,其中data
是二维数组,m
是行索引或分片,n
是列索引或分片。 - 那么,
data[0, 1]
就表示获取data
中第一行第二列的元素。如果省略第二个参数n
的话表示获取所有列,data[0]
就表示获取整个第一行,相当于data[0, :]
。 - 如果想要获取第一列则可以写成
data[:,0]
;如果想获取 2、3 两行可以写成data[1:3]
,相当于data[1:3, :]
。
data = np.array([[1, 2], [3, 4], [5, 6]])
print(data[0, 1])
# 输出:2
print(data[:, 0])
# 输出:[1 3 5]
print(data[1:3])
# 输出:
# [[3 4]
# [5 6]]
numpy 中的高级索引:
布尔索引 :
data = np.array([[1, 2], [3, 4], [5, 6]])
print(data > 3)
#输出:[[False False]
# [False True]
# [ True True]]
print(data[data>3])
#输出:[4 5 6]
# 大于 3 并且小于 5
print(data[(data>3) & (data<5)])
#输出:[4]
# 大于 3 或者小于 2
print(data[(data > 3) | (data < 2)])
# 输出:[1 4 5 6]
# 大于 3 或者不小于 2(即大于等于 2)
print(data[(data > 3) | ~(data < 2)])
# 输出:[2 3 4 5 6]
# 等于 3
print(data[data == 3])
# 输出:[3]
# 不等于 3
print(data[data != 3])
# 输出:[1 2 4 5 6]
and
改用&
,or
改用|
,not
改用~
,并且每个条件要用括号括起来。
实用方法:
arange() 方法:
numpy 中的 arange()
方法和 Python 中的 range()
用法类似,不同之处在于 arange()
方法生成的是数组,而 range()
方法生成的是 range
类型的序列。
# 生成 1-9 的数组
print(np.arange(1, 10))
# 输出:[1 2 3 4 5 6 7 8 9]
# 生成 0-9 的数组
print(np.arange(10))
# 输出:[0 1 2 3 4 5 6 7 8 9]
# 生成 1-9 的数组,步长为 2
print(np.arange(1, 10, 2))
# 输出:[1 3 5 7 9]
随机方法:
numpy 中的 np.random.rand()
方法和 Python 中 random.random()
方法类似,都是生成 [0, 1)
之间的随机小数。不同的是,numpy 中的 np.random.rand()
方法可以生成多个 [0, 1)
之间的随机小数,只需我们传入要生成的随机数组的形状(shape)即可。
# 不传参数时
print(np.random.rand())
# 输出:0.1392571183916036
# 传入一个参数时
print(np.random.rand(3))
# 输出:[0.7987698 0.52115291 0.70452156]
# 传入多个参数时
print(np.random.rand(2, 3))
# 输出:
# [[0.08539006 0.97878203 0.23976172]
# [0.34301963 0.48388704 0.63304024]]
numpy 中的 np.random.randint()
方法和 Python 中的 random.randint()
类似,
不同之处在于,random.randint(m, n)
生成的是 [m, n]
之间的整数,
而 np.random.randint(m, n)
生成的是 [m, n)
之间的整数。
# 不传入形状时
print(np.random.randint(0, 5))
# 输出:3
# 形状为一维数组时
print(np.random.randint(0, 5, 3))
# 输出:[4 0 1]
# 形状为二维数组时
print(np.random.randint(0, 5, (2, 3)))
# 输出:
# [[0 2 1]
# [4 2 0]]
genfromtxt() 方法:
genfromtxt()
方法用于文件的读取。
genfromtxt()
方法常用的参数有两个,分别是数据源和分隔符。假设我们要用 numpy 读取一个以逗号分隔的 CSV 文件,可以这样写:
data = np.genfromtxt('data.csv', delimiter=',')
第一个参数是数据源,可以是本地文件的路径,也可以是网络文件的地址。
delimiter
参数用于指定分隔符,CSV 文件一般是用逗号作为分隔符,当遇到其他符号分隔的文件时,用delimiter
参数进行指定即可。
genfromtxt()
方法的返回值是一个多维数组。
索引:
numpy 中多维数组的索引也是从 0 开始,以多维数组的长度减 1 结束,可以直接使用 data[-1]
获取数组中的最后一个元素。写法也和列表索引一样:
data = np.array([1, 2, 3])
print(data[0])
# 输出:1
print(data[-1])
# 输出:3
分片:
多维数组的分片和列表的分片也是基本类似的,形如 data[m:n]
。分片是左闭右开区间,即包含 m 不包含 n,也就是获取索引为 m 到 n-1 之间的元素(包含 m 和 n-1)。
data = np.array([1, 2, 3])
print(data[0:2]) # 获取索引为 0 和 1 的元素
# 输出:[1 2]
多维数组也同样支持反向索引分片,使用
data[-3:-1]
也同样能得到[1 2]
。
在列表分片时,冒号前后的值是可以省略的。省略后冒号前默认为 0,冒号后默认为列表的长度。这同样适用于多维数组,所以通过冒号前后值的省略,有如下分片小技巧:
data = np.array([1, 2, 3])
# 获取前 2 个元素
print(data[:2])
# 输出:[1 2]
# 获取后 2 个元素
print(data[-2:])
# 输出:[2 3]
# 获取所有元素
print(data[:])
# 输出:[1 2 3]
注意:列表分片是将分片后的数据复制了一份,而多维数组的分片则是返回原数据其中的一块,并没有复制数据。
因此,对列表分片后的数据进行更改不会影响原数据,但对多维数组分片后的数据进行更改会影响到原数据。
# 列表
lst_data = [1, 2, 3]
lst_data2 = lst_data[:]
lst_data2[0] = 6
print(lst_data)
# 输出:[1, 2, 3]
# 多维数组
arr_data = np.array([1, 2, 3])
arr_data2 = arr_data[:]
arr_data2[0] = 6
print(arr_data)
# 输出:[6 2 3]
numpy 设计的目的是处理大数据,所以,numpy 中的切片默认不会复制一份副本,而是返回原数据中的一块,被称为视图(View)。如果想要得到一份副本,则需要手动调用 copy()
方法进行复制,例如:arr_data[:].copy()
。
分片支持传入第三个参数——步长(分片时每隔几个数据取一次值,步长的默认值为 1)
data = np.array([1, 2, 3, 4, 5, 6])
print(data[::2]) # 省略前两个参数
# 输出:[1 3 5]
上述例子中省略了前两个参数,默认为 0 和 6,步长为 2。所以
data[::2]
等价于data[0:6:2]
,作用是索引在 0 到 5 之间的元素,且索引每次加 2。最终将得到索引为 0、2、4 的元素,结果为[1 3 5]
。
当步长为负数时,会将顺序反转。
data = np.array([1, 2, 3, 4, 5, 6])
print(data[::-1]) # 省略前两个参数
# 输出:[6 5 4 3 2 1]
可以利用这个特性来实现列表或多维数组的快速反转。
numpy的方法
求平均值的 mean() 方法,最大值的 max()
方法、求最小值的 min()
方法、求和的 sum()
方法
求中位数的median()方法,求极差的ptp()方法,求标准差的std()方法,求方差的var()方法
import numpy as np
data = np.array([4, 2, 3, 7])
print(np.mean(data))
#输出:4.0
print(np.median(data))
#输出:3.5
print(np.min(data))
#输出:2
print(np.max(data))
#输出:7
print(np.ptp(data))
#输出:5
print(np.std(data))
#输出:1.8708286933869707
print(np.var(data))
#输出:3.5
- 离中趋势是指一组数据中各数据值以不同程度的距离偏离其中心(平均数)的趋势。其常用指标有 极差、方差 和标准差。
- 极差是一组数据的最大值减去最小值得到的,反应了数据变动的最大范围。
- 方差的计算方式是:将一组数据中的每个数减去这组数据的平均数,然后将得到的结果进行平方求和,最后再除以数据的个数。
- 标准差是方差的平方根。
- 方差和标准差都能反映数据的离散程度,也就是数据的波动程度。方差和标准差的值越小,说明数据越稳定。