1 介绍
numpy主要是解决对多维数组的计算问题
2 ndarray对象
前面学到pandas有两个对象:Series和DataFrame;
numpy有一个基本的数据对象:ndarray
ndarray的多个属性:
属性 | 含义 |
---|---|
T | 转置,与self.transpose( )相同,如果维度小于2返回self |
size | 数组中元素个数 |
itemsize | 数组中单个元素的字节长度 |
dtype | 数组元素的数据类型对象 |
ndim | 数组的维度 |
shape | 数组的形状 |
data | 指向存放数组数据的python buffer对象 |
flat | 返回数组的一维迭代器 |
imag | 返回数组的虚部 |
real | 返回数组的实部 |
nbytes | 数组中所有元素的字节长度 |
调用 ndarray 的构造函数创建一个 ndarray 对象:
np.ndarray( shape=, dtype=, buffer= , offset=, order=)
参数说明:
参数 | 类型 | 作用 |
---|---|---|
shape | int型tuple | 多维数组的形状 |
dtype | data-type | 数组中元素的类型 |
buffer | 用于初始化数组的buffer,通常是一个array | |
offset | int | buffer中用于初始化数组的首个数据的偏移 |
strides | int型tuple | 每个轴的下标增加1时,数据指针在内存中增加的字节数 |
order | ‘C’ 或者 ‘F’ | ‘C’:行优先;‘F’:列优先 |
又或者,我们可以直接调用NumPy的array函数即可
NumPy的array函数:
np.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
参数说明:
名称 | 描述 |
---|---|
object | 数组或嵌套的数列 |
dtype | 数组元素的数据类型,可选 |
copy | 对象是否需要复制,可选 |
order | 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认) |
subbok | 默认返回一个与基类类型一致的数组 |
ndmin | 指定生成数组的最小维度 |
ndarray是一个类,np.ndarray() 是它的构造函数,得到一个 ndarray 对象
array() 是为了便于创建一个 ndarray对象的函数。
两者得到的结果其实是一样的。
import numpy as np
mat1 = np.array([[1, 2, 3], [4, 5, 6]])
print("mat1 type:{}".format(type(mat1)))
print("mat1 dtype:{}".format(mat1.dtype))
mat2 = np.ndarray(shape=(2, 3), dtype=np.int32)
print("mat2 type:{}".format(type(mat2)))
print("mat2 dtype:{}".format(mat2.dtype))
输出:
mat1 type:<class 'numpy.ndarray'>
mat1 dtype:int32
mat2 type:<class 'numpy.ndarray'>
mat2 dtype:int32
3 数据类型
3.1 dtype对象
以下这些数值类型实际上是 dtype 对象的实例,也是一个对象,描述了如何解释与数组项对应的固定大小的内存块中的字节。(数据类型与C语言类似。)
名称 | 描述 |
---|---|
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
dtype
对象构造:
numpy.dtype(object, align, copy)
参数说明:
object
:表示要转换为的数据类型对象。align
:若为true
,在内存块填充字段将中以 C 结构进行排列。copy
:复制 dtype 对象 ,如果为false
,则表示对内置数据类型对象的引用。
3.2 dtype 生成数据类型对象
dtype的主要作用是定义复合类型结构的数组,有多个基本数据类型组成的新数据类型
# 复合类型数组的构造
import numpy as np
stu = np.dtype([('name', 'U3'), ('age', 'i4'), ('socre', 'f4')])
stu_list = np.array([('Tom', 21, 60), ('Yan', 20, 59)], dtype=stu)
print(stu_list)
运行结果:[('Tom', 21, 60.) ('Yan', 20, 59.)]
4 Numpy数组/矩阵创建
4.1 从原生的数组创建
① numpy.empty
用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组
函数结构:
numpy.empty(shape, dtype = float, order = 'C')
参数说明:
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | 有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
② numpy.zeros
用于创建指定大小的数组,数组元素以 0 来填充:
函数结构:
numpy.zeros(shape, dtype = float, order = 'C')
参数说明:
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | ‘C’ 用于 C 的行数组,或者 ‘F’ 用于 FORTRAN 的列数组 |
③ numpy.ones
用于创建指定形状的数组,数组元素以 1 来填充:
函数结构:
numpy.ones(shape, dtype = None, order = 'C')
参数说明:
参数 | 描述 |
---|---|
shape | 数组形状 |
dtype | 数据类型,可选 |
order | ‘C’ 用于 C 的行数组,或者 ‘F’ 用于 FORTRAN 的列数组 |
④ numpy.arange
用于创建按规则生成的数组:
函数结构:
numpy.arange(start, stop, step, dtype = None)
参数说明:
参数 | 描述 |
---|---|
start | 开始位置,数字,可选项,默认起始值为0 |
stop | 停止位置,数字 |
step | 步长,数字,可选项, 默认步长为1,如果指定了step,则还必须给出start。 |
dtype | 输出数组的类型。 如果未给出dtype,则从其他输入参数推断数据类型。 |
⑤ 经典例题:创建一个8x8的国际象棋棋盘矩阵
# 创建一个8x8的国际象棋
import numpy as np
# 方法一
a = np.ones((8, 8), dtype=int)
# stop为空意味着自动结束, 1::2为行第二行开始到自动结束,并且步长为2,::2为列从零开始到自动结束步长为2
a[1::2, ::2] = 0
# ::2为行第一行开始到自动结束,并且步长为2,1::2为列从二开始到自动结束步长为2
a[::2, 1::2] = 0
print(a)
# 方法二
b = np.ones((8, 8), dtype=int)
for i in range(8):
for j in range(8):
if(i+j) % 2 == 0:
b[i, j] = 0
print(b)
运行结果:
4.2 从已有数组创建
① numpy.asarray
生成一个和参数 a 大小相同的数组。
函数结构:
numpy.asarray(a, dtype = None, order = None)
参数说明:
参数 | 描述 |
---|---|
a | 任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组 |
dtype | 数据类型,可选 |
order | 可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。 |
② numpy.frombuffer
用于实现动态数组,将数据以流的形式读入转化成ndarray对象 。
函数结构:
numpy.frombuffer(buffer, dtype=, count=-1, offset=0)
参数说明:
参数 | 描述 |
---|---|
buffer | 可以是任意对象,会以流的形式读入。 |
dtype | 返回数组的数据类型,可选 |
count | 读取的数据数量,默认为-1,读取所有数据。 |
offset | 读取的起始位置,默认为0。 |
4.3 使用特殊库函数生成数组
random
模块来处理随机数,用来随机生成离群点或生成噪声图像
numpy.random
模块分为四个部分:
-
简单随机数: 产生简单的随机数据,可以是任何维度
-
排列:将所给对象随机排列
-
分布:产生指定分布的数据,如高斯分布等
-
生成器:种随机数种子,根据同一种子产生的随机数是相同的
(1)随机数是由随机种子根据一定的计算方法计算出来的数值。所以,只要计算方法一定,随机种子一定,那么产生的随机数就不会变。
(2)只要用户不设置随机种子,那么在默认情况下随机种子来自系统时钟(即定时/计数器的值)
(3)随机数产生的算法与系统有关,Windows和Linux是不同的,也就是说,即便是随机种子一样,不同系统产生的随机数也不一样。
常用函数总结:参考文章
-
np.random.uniform
:生成固定范围的随机数numpy.random.uniform(low,high,size)
-
np.random.rand
:通过本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。随机样本取值范围是[0,1),不包括1。np.random.rand(d0,d1,d2……dn)
-
np.random.randn()
:返回一个或一组服从标准正态分布的随机样本值 -
np.random.random(size=)
:用法与np.random.rand 一样,就size要加括号np.random.random((1000, 20))# 上面这个就代表生成1000行 20列的浮点数,浮点数都是从0-1中随机。
-
np.random.randint()
:返回一个随机整型数,范围从低(包括)到高(不包括),即[low, high)。 如果没有写参数high的值,则返回[0,low)的值。numpy.random.randint(low, high=None, size=None, dtype='l')
5 数组切片
注意:numpy 的切片返回的是原数据的视图,即不会创建新的内存地址,而是对原数据内存地址的引用。所以对numpy 切片结果进行修改会发现,原数据也一起发生了改变。
5.1 使用slice函数
从原数组中切割出一个新数组。
函数结构:
class slice(start, stop[, step])
参数说明:
start
为切片起始位置stop
为切片终止位置(不包括以stop
索引的元素)step
为步长。
注意:slice
是一个实现切片的对象,主要用在切片操作函数里的参数传递。
# 使用slice函数对数组进行切片
import numpy as np
a = np.arange(10)
cut = slice(2, 8, 2)
print(a[cut])
运行结果:[2 4 6]
5.2 直接使用下标索引
import numpy as np
b = np.arange(10)
c = b[2:8:2]
print(c)
6 数组索引
6.1 整数数组索引
直接看代码
# 整数数组索引
import numpy as np
a = np.arange(10, 1, -1)
print("a数组为\n", a)
b = a[np.array([3, 3, 1, 8])]
print("索引是3, 3, 1, 8的数组\n", b)
c = a[np.array([3, 3, -4, -2])]
print("索引是3, 3, -4, -2的数组\n", c)
d = a[np.array([[1, 1], [2, 3]])]
print("索引是[[1, 1], [2, 3]]的数组\n", d)
6.2 布尔索引
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。用作索引的布尔数组的处理方式与索引数组完全不同。布尔数组的形状必须与要索引的数组的初始尺寸相同。在最直接的情况下,布尔数组具有相同的形状:
# 布尔索引
import numpy as np
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print('我们的数组是:')
print(x)
print('\n')
# 现在我们会打印出大于 5 的元素
print('大于 5 的元素是:')
print(x[x > 5])
6.3 花式索引
花式索引指的是利用整数数组进行索引。花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。
6.4 总结
7 数组计算
7.1 基本计算
不管是符号方法还是函数方法,都必须保证操作的数组具有相同的形状。
符号方法:四则运算符 +、- 、/
函数方法:对应的 numpy 模块函数分别是 add
、subtract
、multiply
和 divide
import numpy as np
a = np.arange(25).reshape(5, 5)
b = np.ones(shape=(5, 5)) * 2
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a ** 2)
num1 = [1, 1, 1]
num2 = [1, 1, 1]
np.add(num1, num2, out=num2)
np.divide(num1, 2, out=num1)
np.negative(num1, out=num1)
np.multiply(num1, num2, out=num1)
print(num1)
7.2 统计计算
两种方式计算:
- 对整个数组进行计算;
- 对源数组的某个轴向的数据进行统计计算;
Numpy 的基本统计计算方法如下表所示:
方法名 | 说明 |
---|---|
sum | 聚合计算;对数组中全部或某轴元素求和 |
mean | 聚合计算;算数平均数 |
std、var | 聚合计算;分别表示标准差和方差 |
min、max | 最大值和最小值 |
argmin、argmax | 分别表示最大和最小元素的索引 |
cumsum | 非聚合计算;所有元素的的累积和 |
cumprod | 非聚合计算;所有元素的累计积 |
线性代数等等庞大的数学函数库:
矩阵函数 | 说明 |
---|---|
np.diag( ndarray) np.diag( [x,y,…]) | 以一维数组的形式返回方阵的对角线(或非对角线)元素将一维数组转化为方阵(非对角线元素为0) |
np.dot(ndarray, ndarray) | 矩阵乘法 |
np.trace( ndarray) | 计算对角线元素的和 |
排序函数 | 说明 |
---|---|
np.sort( ndarray) | 排序,返回副本 |
np.unique(ndarray) | 返回ndarray中的元素,排除重复元素之后,并进行排序 |
np.intersect1d( ndarray1, ndarray2) np.union1d( ndarray1, ndarray2) np.setdiff1d( ndarray1, ndarray2) np.setxor1d( ndarray1, ndarray2) | 返回二者的交集并排序。返回二者的并集并排序。返回二者的差。返回二者的对称差 |
一元计算函数 | 说明 |
---|---|
np.abs(ndarray) np.fabs(ndarray) | 计算绝对值 计算绝对值(非复数) |
np.mean(ndarray) | 求平均值 |
np.sqrt(ndarray) | 计算x^0.5 |
np.square(ndarray) | 计算x^2 |
np.exp(ndarray) | 计算e^x |
log、log10、log2、log1p | 计算自然对数、底为10的log、底为2的log、底为(1+x)的log |
np.sign(ndarray) | 计算正负号:1(正)、0(0)、-1(负) |
np.ceil(ndarray) np.floor(ndarray) np.rint(ndarray) | 计算大于等于改值的最小整数 计算小于等于该值的最大整数 四舍五入到最近的整数,保留dtype |
np.modf(ndarray) | 将数组的小数和整数部分以两个独立的数组方式返回 |
np.isnan(ndarray) | 返回一个判断是否是NaN的bool型数组 |
np.isfinite(ndarray) np.isinf(ndarray) | 返回一个判断是否是有穷(非inf,非NaN)的bool型数组返回一个判断是否是无穷的bool型数组 |
cos、cosh、sin、sinh、tan、tanh | 普通型和双曲型三角函数 |
arccos、arccosh、arcsin、arcsinh、arctan、arctanh | 反三角函数和双曲型反三角函数 |
np.logical_not(ndarray) | 计算各元素not x的真值,相当于-ndarray |
多元计算函数 | 说明 |
---|---|
np.add(ndarray, ndarray) np.subtract(ndarray, ndarray) np.multiply(ndarray, ndarray) np.divide(ndarray, ndarray) np.floor_divide(ndarray, ndarray) np.power(ndarray, ndarray) np.mod(ndarray, ndarray) | 相加 相减 乘法 除法 圆整除法(丢弃余数) 次方 求模 |
np.maximum(ndarray, ndarray) np.fmax(ndarray, ndarray) np.minimun(ndarray, ndarray) np.fmin(ndarray, ndarray) | 求最大值 求最大值(忽略NaN) 求最小值 求最小值(忽略NaN) |
np.copysign(ndarray, ndarray) | 将参数2中的符号赋予参数1 |
np.greater(ndarray, ndarray) np.greater_equal(ndarray, ndarray) np.less(ndarray, ndarray) np.less_equal(ndarray, ndarray) np.equal(ndarray, ndarray) np.not_equal(ndarray, ndarray) | > >= < <= == != |
logical_and(ndarray, ndarray) logical_or(ndarray, ndarray) logical_xor(ndarray, ndarray) | &|^ |
np.dot( ndarray, ndarray) | 计算两个ndarray的矩阵内积 |
np.ix_([x,y,m,n],…) | 生成一个索引器,用于Fancy indexing(花式索引) |
8 数组操作
8.1 修改数组形状
函数 | 描述 |
---|---|
reshape | 不改变数据的条件下修改形状 |
flat | 数组元素迭代器 |
flatten | 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组 |
ravel | 返回展开数组 |
① numpy.reshape
函数格式:
numpy.reshape(arr, newshape, order='C')
参数说明:
- arr:要修改形状的数组
- newshape:整数或者整数数组,原数组元素个数应当和新数组元素个数相同(新的形状应当兼容原有形状)
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。
② numpy.ndarray.flatten
计算展平的数组,返回一份数组拷贝,对拷贝所做的修改不会影响原始数组
函数格式:
ndarray.flatten(order='C')
参数说明:
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
import numpy as np
arr = np.arange(8)
print(arr)
# 修改数组形状
new_arr = arr.reshape(4, 2)
print(new_arr)
# 计算展平的数组
arr = np.arange(8).reshape(2, 4)
print(arr)
print(arr.flatten())
print(arr.flatten(order='F'))# 按列展开
8.2 翻转数组
函数 | 描述 |
---|---|
transpose | 对换数组的维度 |
ndarray.T | 和 self.transpose() 相同 |
rollaxis | 向后滚动指定的轴 |
swapaxes | 对换数组的两个轴 |
① numpy.transpose
用于对换数组的维度
函数格式:
numpy.transpose(arr, axes)
参数说明:
- arr:要操作的数组
- axes:整数列表,对应维度,通常所有维度都会对换。
import numpy as np
arr = np.arange(8).reshape(2, 4)
print(arr)
print(np.transpose(arr))
8.3 修改数组维度
维度 | 描述 |
---|---|
broadcast | 产生模仿广播的对象 |
broadcast_to | 将数组广播到新形状 |
expand_dims | 扩展数组的形状 |
squeeze | 从数组的形状中删除一维条目 |
① numpy.expand_dims
numpy.expand_dims
函数通过在指定位置插入新的轴来扩展数组形状,函数格式如下:
numpy.expand_dims(arr, axis)
参数说明:
- arr:输入数组
- axis:新轴插入的位置
import numpy as np
arr = np.arange(4).reshape(2,2)
#在0轴拓展一个维度
new_arr = np.expand_dims(arr, axis=0)
print(arr.shape)
print(new_arr.shape)
#扩展后的数组
print(new_arr)
原本的0轴位置新增加了一个维度
② numpy.squeeze
从给定数组的形状中删除一维的条目
函数格式:
numpy.squeeze(arr, axis)
参数说明:
- arr:输入数组
- axis:整数或整数元组,用于选择形状中一维条目的子集
import numpy as np
arr = np.arange(4).reshape(1,2,2)
#删除0轴的维度
new_arr = np.squeeze(arr, axis=0)
print(arr.shape)
print(new_arr.shape)
print(arr)
print(new_arr)
8.4 连接数组
函数 | 描述 |
---|---|
concatenate | 连接沿现有轴的数组序列 |
stack | 沿着新的轴加入一系列数组。 |
hstack | 水平堆叠序列中的数组(列方向) |
vstack | 竖直堆叠序列中的数组(行方向) |
① numpy.concatenate
用于沿指定轴连接相同形状的两个或多个数组
函数格式:
numpy.concatenate((a1, a2, ...), axis)
参数说明:
- a1, a2, …:相同类型的数组
- axis:沿着它连接数组的轴,默认为 0
import numpy as np
#创建两个2*2的数组
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
print(a)
print(b)
#沿0轴方向连接
print(np.concatenate((a, b), axis=0))
#沿1轴方向连接
print(np.concatenate((a, b), axis=1))
② numpy.stack
用于沿新轴连接数组序列
函数格式:
numpy.stack(arrays, axis)
参数说明:
- arrays:相同形状的数组序列
- axis:返回数组中的轴,输入数组沿着它来堆叠
import numpy
arr_1 = numpy.arange(1, 7).reshape((2, 3))
arr_2 = numpy.arange(7, 13).reshape((2, 3))
arr_3 = numpy.arange(13, 19).reshape((2, 3))
arr_4 = numpy.arange(19, 25).reshape((2, 3))
print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=0))
print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=0).shape)
print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=1))
print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=1).shape)
print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=2))
print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=2).shape)
需要注意的是:axis 等于几就说明在哪个维度上进行堆叠。
当 axis=0 的时候,意味着整体,也就是一个2行3列的数组。所以对于0维堆叠,相当于简单的物理罗列,比如这四个数组代表的是4张图像的数据,进行0维堆叠也就是把它们按顺序排放了起来,形成了一个(4,2,3)的3维数组。
当 axis=1 的时候,意味着第一个维度,也就是数组的每一行。所以对于1维堆叠,4个2行3列的数组,各自拿出自己的第一行数据进行堆叠形成3维数组的第一“行”,各自拿出自己的第二行数据进行堆叠形成3维数组的第二“行”,从而形成了一个(2,4,3)的3维数组。
当 axis=2 的时候,意味着第二个维度,注意:千万不要理解成2维堆叠是对每一列拿出来进行堆叠!这个堆叠是对于整个维度来讲的,我们把一维空间理解为一条线,而二维空间则是一个平面。从第二个维度堆叠可以看作平面与平面的堆叠。
与 numpy.concatenate()
函数的区别:
concatenate()
函数用于实现数组的拼接,stack()会增加数组的维度,而 concatenate()
不会增加数组的维度。
8.5 分割数组
函数 | 数组及操作 |
---|---|
split | 将一个数组分割为多个子数组 |
hsplit | 将一个数组水平分割为多个子数组(按列) |
vsplit | 将一个数组垂直分割为多个子数组(按行) |
① numpy.split
沿特定的轴将数组分割为子数组
函数格式:
numpy.split(arr, indices_or_sections, axis)
参数说明:
- arr:被分割的数组
- indices_or_sections:果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭)
- axis:设置沿着哪个方向进行切分,默认为 0,横向切分,即水平方向。为 1 时,纵向切分,即竖直方向。
import numpy as np
arr = np.arange(9)
print(arr)
arr_1 = np.split(arr, 3)
arr_2 = np.split(arr, [4, 7])
print(arr_1)
print(arr_2)
8.6 数组元素的添加与删除
函数 | 元素及描述 |
---|---|
resize | 返回指定形状的新数组 |
append | 将值添加到数组末尾 |
insert | 沿指定轴将值插入到指定下标之前 |
delete | 删掉某个轴的子数组,并返回删除后的新数组 |
unique | 查找数组内的唯一元素 |
① numpy.resize
返回指定大小的新数组。如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
函数格式:
numpy.resize(arr, shape)
参数说明:
- arr:要修改大小的数组
- shape:返回数组的新形状
import numpy as np
arr = np.arange(6).reshape(2,3)
print(arr)
new_arr = np.resize(arr, (3,2))
print(new_arr)
new_arr = np.resize(arr, (3,3))
print(new_arr)
new_arr = np.resize(arr, (2,2))
print(new_arr)
可以看到不同于 reshape
函数,resize
函数支持新数组元素个数与原数组不同,当时新数组小于原数组使会按行优先顺序进行元素排列,当新数组大于原数组时会从头开始填充元素。
② numpy.append
在数组的末尾添加值。 追加操作会分配整个数组,并把原来的数组复制到新数组中。
输入数组的维度必须匹配否则将生成 ValueError。
append
函数返回的始终是一个一维数组。
函数格式:
numpy.append(arr, values, axis=None)
参数说明:
- arr:输入数组
- values:要向
arr
添加的值,需要和arr
形状相同(除了要添加的轴) - axis:默认为 None。当 axis 无定义时,是横向加成,返回总是为一维数组!当 axis 有定义的时候,分别为0和1的时候。当 axis 有定义的时候,分别为0和1的时候(列数要相同)。当 axis 为1时,数组是加在右边(行数要相同)。
③ numpy.insert
在给定索引之前,沿给定轴在输入数组中插入值。
如果值的类型转换为要插入,则它与输入数组不同。 插入没有原地的,函数会返回一个新数组。 此外,如果未提供轴,则输入数组会被展开。
函数格式:
numpy.insert(arr, obj, values, axis)
参数说明:
- arr:输入数组
- obj:在其之前插入值的索引
- values:要插入的值
- axis:沿着它插入的轴,如果未提供,则输入数组会被展开
④ numpy.delete
返回从输入数组中删除指定子数组的新数组。
与 insert() 函数的情况一样,如果未提供轴参数,则输入数组将展开。
函数格式:
Numpy.delete(arr, obj, axis)
参数说明:
- arr:输入数组
- obj:可以被切片,整数或者整数数组,表明要从输入数组删除的子数组
- axis:沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开
⑤ numpy.unique
用于去除数组中的重复元素。
函数格式:
numpy.unique(arr, return_index, return_inverse, return_counts)
参数说明:
- arr:输入数组,如果不是一维数组则会展开
- return_index:如果为
true
,返回新列表元素在旧列表中的位置(下标),并以列表形式储 - return_inverse:如果为
true
,返回旧列表元素在新列表中的位置(下标),并以列表形式储 - return_counts:如果为
true
,返回去重数组中的元素在原数组中的出现次数
9 广播
通过扩展数组的方法来实现相加、相减、相乘等操作的机制。
当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。
广播的规则:
- 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
- 输出数组的形状是输入数组形状的各个维度上的最大值。
- 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
简单理解:对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
- 数组拥有相同形状。
- 当前维度的值相等。
- 当前维度的值有一个是 1。
若条件不满足,抛出 “ValueError: frames are not aligned” 异常。
import numpy as np
a = np.array([[0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]])
b = np.array([1, 2, 3])
print(a + b)
【练习】计算减去每一行平均值的矩阵
import numpy as np
X = np.array([[7,0,5,2,4,7,7,3,0,4],
[6,0,7,6,5,1,4,4,0,6],
[2,0,5,3,2,1,8,2,3,1],
[9,0,3,4,8,0,6,3,3,6],
[3,0,7,1,6,4,5,8,3,5]])
Y = X - X.mean(axis=1, keepdims=True)
print(Y)
10 浅拷贝与深拷贝
copy 操作分为三种:无拷贝、浅拷贝、深拷贝。
10.1 无拷贝
拷贝操作没有发生,只是简单的复制了对象地址,不会产生新的对象。
故对该对象进行操作后会改变原来的对象值。
import numpy as np
a = np.arange(12)
b = a # 仅仅是引用的复制
print("无拷贝\n")
print(b is a)
print(id(a))
print(id(b))
在进行赋值操作时,Python 进行的时引用传递,两个变量指向同一块内存区域
10.2 视图或浅拷贝
浅拷贝内存地址不同,但不会 copy 底层的数据,所以改变一个对象的数据时另一个也会改变。
切片操作就是一种浅拷贝。浅拷贝不同的 ndarray 对象可以共享相同的数据区。view
方法可以新建一个新的 ndarray,但是只会 copy 父对象,不会 copy 底层的数据,共用原始引用指向的对象数据。
import numpy as np
a = np.arange(6).reshape(3, 2)
b = a.view()
print(a)
b.shape = 2, 3
print(b)
print(a is b)
print(id(a))
print(id(b))
10.3 副本或深拷贝
ndarray.copy()
函数创建一个副本。 对副本数据进行修改,不会影响到原始数据,它们物理内存不在同一位置。
# 深拷贝
import numpy as np
a = np.arange(6).reshape(3, 2)
b = a.copy()
print(a is b)
print(id(a))
print(id(b))