初识NumPy (二)

[初识NumPy(一)](https://learnku.com/articles/77846 "初识NumPy(一)")中介绍了NumPy的基础知识,感兴趣的话可以看看,如果感觉过得去的话点点赞:laughing:

基本的索引和切片

NumPy数组的索引是一个丰富的主题,因为在获取数据子集或者单个元素有很多种,一维数组很简单,它们和Python列表功能差不多,不过NumPy数组,当你将一个值赋值给一个切片时,该值会自动传播,跟列表的区别是,数组切片时原始数组的视图。视图的任何修改都会影响源数组上,数据不会被复制。
import numpy as np

arr = np.arange(10)
print(arr)  # [0 1 2 3 4 5 6 7 8 9]

print(arr[5]) # 5
print(arr[5:8])
arr[5:8] = 20  # [5 6 7]

print(arr) # [ 0  1  2  3  4 20 20 20  8  9]
import numpy as np
arr = np.arange(10)
print(arr)  # [0 1 2 3 4 5 6 7 8 9]
print(arr[5:8]) # [5 6 7]
arr_slice = arr[5:8]
print(arr_slice)  # [5 6 7]
arr_slice[1] = 12345  
print(arr) # [    0     1     2     3     4     5 12345     7     8     9]
arr_slice[:] = 66 
print(arr)  # [ 0  1  2  3  4 66 66 66  8  9]
print(arr_slice)  # [66 66 66]

在上述例子,当我修改arr_slice中的值时,arr源数组中也会变动,因为是NumPy直接修改的是内存中的源数据,并没有将数据复制一份为副本,想象一下,如果NumPy是使用副本的话,当有大量数据时,数据的复制来复制去会耗费大量的性能和内存,如果你明确的要进行操作副本的话,要是用copy方法,例如: arr[5:8].copy(), 通过 copy()创建副本是独立,对副本修改不会影响原始数组,在需要对数组进行修改时而又不想影响原始数组时非常有用。

对多维数组的操作
在一个二维数组中,各索引位置上不再是元素,而是一个一维数组
import numpy as np
arr2d  = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d[2])  # [7 8 9]

# 可以对各个元素进行递归访问,也可以传入一个逗号隔开的索引列表来选取单个元素, 下面两种方式等等价的
print(arr2d[0][2])  # 3
print(arr2d[0, 2])  # 3

数组转置额轴对换

import numpy as py
arr  = np.arange(15).reshape((3, 5))
print(arr)
"""
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
"""
1. np.arange(15).reshape((3, 5)) 是NumPy中一种数组创建和重塑的组合。它的作用是创建一个包含014的整数序列,并将重新塑性为一个35列的二维数组
2. np.arange(15) 创建一个包含014的整数序列的一维数组,然后通过调用 reshape((3, 5))方法,将这个一维数组重塑为一个35列的二维数组
3. 这种操作在需要创建特定形状的数组或者将一维数组转换为二维数组时非常有用,通过改变 reshape()中的参数创建不同形状的数组, 重塑操作需要确保原始数据中的元素数量重塑后的形状相匹配
T属性
import numpy as np
arr = np.arange(15).reshape((3, 5))
print(arr)
"""
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
 """

print(arr.T)
"""
[[ 0  5 10]
 [ 1  6 11]
 [ 2  7 12]
 [ 3  8 13]
 [ 4  9 14]]
"""
arr.T : 用于获取数组的转置
对于二维数组,转置操作会将数组的行和列进行交换,即行变成列,列变成行,转置操作不会改变原始数据数组的数据,而是返回一个新的转置后的数组,
对于一维数组,转置操作不会产生任何效果,仍然返回原始数组,只有二维数组及以上才有具有转置的概念
转置操作在处理数据非常常见,可以用于矩阵计数,数组重组,数组转置等,它可以改变数据的排列方式,方便进行不同的分析和计算

通用函数

通用函数是一种对ndarray中的数据执行元素级运算的函数,可以将其看做简单函数(接受一个或者多个标量值,并产生一个或者多个标量值)的矢量化包装器
sqrt :
sqrt:是NumPy后的一个函数调用,用于计算数组中每个元素的平方根,它接受一个数组作为输入,并返回一个新的数组,其中包含输入数组每个元素的平方根
import numpy as np
arr = np.arange(10)
print(arr)  # [0 1 2 3 4 5 6 7 8 9]

print(np.sqrt(arr)) 
"""
[0.         1.         1.41421356 1.73205081 2.         2.23606798
 2.44948974 2.64575131 2.82842712 3.        ]
"""
exp:
exp: 是NumPy中的一个函数调用,用于计算数组中的每个元素的指数函数值,它接受一个数组作为输入,并返回一个新的数组,其中包含输入数组中每个元素的指数函数值。

指数函数将每个输入值取为底数的指数幂,以自然对数 e 为底

底数的指数幂 : 表示将某个数值作为底数,以另一个数值作为指数进行运算得到的结果。
具体而言,对于底数 a 和指数 b,底数的指数幂运算可以表示为 a^b。在这个运算中,底数 a 表示要进行指数幂运算的数值,指数 b 表示幂次数。

当指数 b 是正整数时,底数的指数幂运算表示将底数连乘 b 次。例如,2^3 表示将底数 2 连乘 3 次,即 2 * 2 * 2,结果为 8。

当指数 b 是负整数时,底数的指数幂运算表示将底数连除 |b| 次。例如,2^-3 表示将底数 2 连除 3 次,即 1 / (2 * 2 * 2),结果为 1/8。

当指数 b 是零时,任何非零底数的指数幂运算结果为 1。例如,2^0 = 1。
自然对数 e 是一个重要的数学常数,它是一个无理数,约等于 2.71828。它的确切值是无限不循环的小数。
import numpy as np
arr = np.arange(10)
print(arr)  # [0 1 2 3 4 5 6 7 8 9]

print(np.exp(arr))
"""
[1.00000000e+00 2.71828183e+00 7.38905610e+00 2.00855369e+01
 5.45981500e+01 1.48413159e+02 4.03428793e+02 1.09663316e+03
 2.98095799e+03 8.10308393e+03]
"""
maximum
maximum : 用于比较两个或者多个数值或者数组,并返回它们之间的最大值
1.对于两个数值: maximum(a, b)返回的是a和b之间的较大值
2.对于两个数组: np.minimum(x, y) 返回一个新的的数组,其中的每一个元素是对应位置上 x , y 两个数组中元素的最大值
3.对于多个数组:np.maximum(a, b, c, ...) 是 NumPy 库中的函数调用,可以比较多个数组,并返回一个新的数组,其中的每个元素是对应位置上多个数组中元素的最大值。

maximun函数可以应用于不同类型的数值,包括整数浮点数,和数组
import numpy as np

# 两个数值的比较 
a = 5 
b = 3 
max_value = maximum(a, b) 
print(max_value) # 输出: 5

# 两个数组的比较
x = np.random.randn(8)
print(x)
"""
[ 1.4749927   1.67181422  0.57457168 -1.01679162 -0.40953417  0.15888697
 -1.57348588 -1.4642116 ]
"""
y = np.random.randn(8)
print(y)
"""
[-1.45959572 -1.78766839 -0.29924779  0.24273894 -1.24544362 -0.6503912
  0.37641994  1.05980487]
"""

print(np.minimum(x, y))
"""
[-1.45959572 -1.78766839 -0.29924779 -1.01679162 -1.24544362 -0.6503912
 -1.57348588 -1.4642116 ]
"""

# 多个数组的比较 
arr1 = np.array([1, 5, 3]) 
arr2 = np.array([2, 4, 6]) 
arr3 = np.array([0, 9, 8]) 
max_array = np.maximum(arr1, arr2, arr3) 
print(max_array) # 输出: [2 9 8]


常见的一元函数
函数 说明
abs, fabs 计算整数, 浮点数或复数的绝对值,对于非负数值,可以使用更快额fabs
sqrt 计算各元素的平方根,相当于 arr** 0.5
square 计算各元素的平方,相当于arr**2
exp 计算各元素的指数e
log,log10,log2,log1p 分别为自然对数(底数为e),底数为10的log,底数为2的log,log(1+x)
sign 计算各元素的正负号:1(正数),0(零),-1(负数)
ceil 计算各元素的ceilingz值,即大于等于该值的最小整数
floor 计算各元素的floor,即小于等于该值额最大整数
rint 将各元素值四舍五入到最接近的整数,保留dtype
modf 将数组的小数和整数部分以两个独立数组的形式返回
isnan 返回一个表示 “哪些值是NaN”(这不是一个数字)的布尔值型的数组
isfinite, isinf 分别返回一个表示“哪些元素是有穷的(非inf,非NaN)”或者 “哪些元素是无穷的”的布尔型数值
cos, cosh, sin, sinh,tan,tanh 普通型和双曲型三角函数
arccos,arccosh, arcsin,arcsinh,arctan,arctanh 反三角函数
logical_not 计算各元素not x的真值,相当于-arr
二元函数
函数 说明
add 将数组中对应的元素相加
subtract 从第一个数组减去第二个数组中的元素
mutiply 数组元素相乘
divide, floor_divide 除法或者向下圆整除法(丢弃余数)
power 对第一个数组中的元素A,根据第二个数组中的相应元素B,计算A*b
maximun, fmin 元素的最大值计算, fmax将忽略NaN
minimum, fmin 元素级的最大值计算,fmin将忽略NaN
mod 元素级的取模计算(除法的余数)
copysign 将第二个数组中的值符号复制第一个数组的值
greater,greater_equal,less,less_equal 执行元素级的比较运算,最终产生布尔型的数组, 相当于 >,>=,<,<=,==,!=
logical_and,logical_or ,logical_xor 执行元素级的真值运算,相当于运算符 & ,

将条件表述为 数组运算

numpy.where函数是一个三元表达式 x if condition else y 的矢量化版本

假设有一个 布尔值数组 和 两个值数组:

import numpy as np

xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])

根据cond的值选取 xarr和yarr的值: 当 cond中的值为True时,选取xarr的值,否则从yarr中选取列表推导式的写法如下:

result = [(x if c else y) for x, y, c in zip(xarr, yarr, cond)]
print(result)   # [1.1, 2.2, 1.3, 1.4, 2.5]

上述方法会有几个问题
1. 它对大数组的处理速度不是很快(因为所有工作都是纯Python完成的)
2. 无法用于多维数组

np.where 函数比 Python 列表推导式快的原因有几个方面
向量化操作: NumPy 提供了许多支持向量化操作的函数和方法,可以在单个操作中同时处理整个数组或数组的切片。这样可以减少循环和逐元素操作,进而提高计算效率。而 Python 列表推导式通常需要通过循环逐个处理列表的元素,执行效率较低
并行计算: NumPy 可以利用现代计算机的并行计算能力,在多核处理器上进行并行计算。通过充分利用计算资源,可以加速 NumPy 数组的计算过程。而 Python 的列表推导式在执行过程中没有内置的并行计算能力

使用where

result = np.where(cond, xarr, yarr)
print(result) # [1.1 2.2 1.3 1.4 2.5]
where第二个和第三个参数不必是数组,他们都可以是标量
假设有一个有一个随机数据组成的矩阵,想将所有正值数替换为2, 所有负值替换为 -2
arr  = np.random.randn(4, 4)
print(arr)
"""
[[ 0.44252018  0.86614172 -0.65812637 -0.51883662]
 [ 0.9757846  -0.44067625  0.85459503  2.19398439]
 [-0.04364949  0.05800473 -1.49901988  0.25206108]
 [ 0.63902518  0.78450113  1.50170198 -1.18778538]]
"""

result = np.where(arr > 0 , 2, -2)
print(result)
"""
[[ 2  2 -2 -2]
 [ 2 -2  2  2]
 [-2  2 -2  2]
 [ 2  2  2 -2]]
"""

聚合计算

sum
用于计算数组中所有元素的总和
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
total = arr.sum()

print(total)  # 输出: 15
mean
用于计算数组中所有元素的平均值
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
average = arr.mean()

print(average)  # 输出: 3.0
mean 和 sum都可以接受一个 axis参数,如果不指定axis参数,则默认将所有元素 求平均值 ,求和,对于二维数组,可以通过 `arr.sum(axis=0)`对每一列进行求和,或者通过`arr.sum(axis=1)`对每一行进行求和,可以通过 arr.mean(axis=0) 对每一列求平均值,或者通过 arr.mean(axis=1) 对每一行求平均值。

基本数组统计方法

方法 说明
sum 对数组中全部或者某轴向的元素求和,零长度的数组的sum为0
mean 对数组中的元素求平均数,零长度的数组的mean为NaN
std, var 分别为标准和方差,自由度可调(默认为n)
min,max 最大值和最小值
aigmin, argmax 最大和最小元素的索引
coumsum 所有元素的累计和
cumprod 所有元素的累计积

在上述的方法中,布尔值会被强制转换为 1(True)和 0(FALSE),因此sum经常用来对布尔型数值进行统计

import numpy as np
arr = np.random.randn(10)
print(arr)
"""
[-1.26011678  0.80656963  0.49409125  2.50827602 -1.174728    1.85180788
  2.16571156  0.49026211  0.75207486 -0.89825599]
"""
print((arr>0).sum()) # 7

any 和 all :any 用来测试数组中是否承载着一个或者多个True, 而all则检查数组中所有元素是否都是True, 所有非0 的元素将会当成True.

bools = np.array([False, False, True, False])
print(bools.any())  # True

print(bools.all()) # False
排序
sort
sort 用于对数组进行原地排序,sort方法会按升序对数组进行排序,并直接修改原始数组,而不返回新的排序后的数组
arr = np.array([3, 1, 4, 2, 5])
arr.sort()
print(arr) #  [1 2 3 4 5]
如果需要获取排序后的结果而不修改原始数组,可以使用 `np.sort(arr)`, 它是 `arr.sort()`方法的函数等效方法,返回排序后的原始数组。
`sort()`方法还可以接受一个可选参数 `axis`,用于指定按照哪个轴排序,默认情况下, `axis`的值为 `-1`,表示按照最后一个轴排序,例如,对于二维数组可以通过`arr.sort(axis=0)`对每一列进行排序,或者通过`arr.sort(axis)=1`对每一行进行排序。
arr = np.random.randn(15).reshape(3, 5)
print(arr)
"""
[[ 1.47247772  0.11908241  1.67117258  1.68789036  0.42267225]
 [ 0.46712596  1.23482755  0.06304478 -1.18022073 -0.42566639]
 [-0.35889245 -0.07408235 -0.08199341 -2.72032726  0.89786726]]
"""
arr.sort(1)
print(arr)
"""
[[ 0.11908241  0.42267225  1.47247772  1.67117258  1.68789036]
 [-1.18022073 -0.42566639  0.06304478  0.46712596  1.23482755]
 [-2.72032726 -0.35889245 -0.08199341 -0.07408235  0.89786726]]
"""
数组的唯一性和集合逻辑
unique
用于找出数组的唯一值并返回已排序的数组
names =np.array(['Bob', 'Joe', 'Will', 'Bob'])
print(np.unique(names))  # ['Bob' 'Joe' 'Will']

ints = np.array([3, 3, 4, 3, 2, 1, 5, 5, 2, 6, 7])
print(np.unique(ints))  # [1 2 3 4 5 6 7]
in1d
判断一个数组中的值是否在另外一个数组,返回一个布尔型数组
values = np.array([6, 0, 0, 0,3, 2,5,6, 4, 7])
print(np.in1d(values,[2, 3, 6]))  # [ True False False False  True  True False  True False False]

常见的数组的集合运算

方法 说明
unique(x) 计算x 中的唯一元素,并返回有序结果
intersect1d(x, y) 计算x 和 y 中的公共元素,并返回有序结果
union1d(x, y) 计算x 和 y 并集,并返回有序结果
in1d(x, y) 得到一个 表示 x的元素是否包含于y 的布尔型数组
setdiff1d(x, y) 集合的差 即元素 在x中不在y中
setxor1d(x, y) 集合的对称差,即存在于一个数组中但不同时存在于两个数组中元素

学海无涯, 只求悟出此道:star2: 大佬们请多指教

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!