第三章:NumPy (3)

木婉清2023/12/02

NumPy(3) 简介

image-2023123003

脑图连接open in new window

位操作与字符串函数

位操作

  • NumPy "bitwise_" 开头的函数是位运算函数

概览

函数描述
bitwise_and对数组元素执行位与操作
bitwise_or对数组元素执行位或操作
invert按位取反
left_shift向左移动二进制表示的位
right_shift向右移动二进制表示的位

注意

也可以使用 "&"、 "~"、 "|" 和 "^" 等操作符进行计算

bitwise_and

  • bitwise_and() 函数对数组中整数的二进制形式执行位与运算
import numpy as np

print("13 和 17 的二进制形式:")
a, b = 13, 17
print(bin(a), bin(b))
print("\n")

print("13 和 17 的位与:")
print(np.bitwise_and(13, 17))
运行结果

13 和 17 的二进制形式: 0b1101 0b10001

13 和 17 的位与: 1

bitwise_or

  • bitwise_or()函数对数组中整数的二进制形式执行位或运算
import numpy as np

print("13 和 17 的二进制形式:")
a, b = 13, 17
print(bin(a), bin(b))
print("\n")

print("13 和 17 的位或:")
print(np.bitwise_or(13, 17))
运行结果

13 和 17 的二进制形式: 0b1101 0b10001

13 和 17 的位或: 29

import numpy as np
print("8 和 25 的二进制形式:")
a, b = 8, 25
print(bin(a), bin(b))
print("8 和 25 的位或:")
print(np.bitwise_or(13, 17))
print("8 和 25 的位与:")
print(np.bitwise_and(13, 17))
运行结果

8 和 25 的二进制形式: 0b1000 0b11001

8 和 25 的位或: 25

8 和 25 的位与: 8

invert

  • invert() 函数对数组中整数进行位取反运算,即 0 变成 1,1 变成 0
import numpy as np

print("13 的位反转,其中 ndarray 的 dtype 是 uint8:")
print(np.invert(np.array([13], dtype=np.uint8)))
# 比较 13 和 242 的二进制表示,我们发现了位的反转

print("13 的二进制表示:")
print(np.binary_repr(13, width=8))

print("242 的二进制表示:")
print(np.binary_repr(242, width=8))
运行结果

13 的位反转,其中 ndarray 的 dtype 是 uint8: [242] 13 的二进制表示: 00001101 242 的二进制表示: 11110010

left_shift

  • left_shift() 函数将数组元素的二进制形式向左移动到指定位置,右侧附加相等数量的 0

right_shift

  • right_shift() 函数将数组元素的二进制形式向右移动到指定位置,左侧附加相等数量的 0

字符串函数

  • 用于对 dtype 为 numpy.string_ 或 numpy.unicode_ 的数组执行向量化字符串操作

概览

函数描述
add()对两个数组的逐个字符串元素进行连接
multiply()返回按元素多重连接后的字符串
center()居中字符串
capitalize()将字符串第一个字母转换为大写
title()将字符串的每个单词的第一个字母转换为大写
lower()数组元素转换为小写
upper()数组元素转换为大写
split()指定分隔符对字符串进行分割,并返回数组列表
splitlines()返回元素中的行列表,以换行符分割
strip()移除元素开头或者结尾处的特定字符
join()通过指定分隔符来连接数组中的元素
replace()使用新字符串替换字符串中的所有子字符串
decode()数组元素依次调用str.decode
encode()数组元素依次调用str.encode
import numpy as np

print(np.char.capitalize("hello world"))
运行结果

Hello world

数学运算函数

  • NumPy 包含大量的各种数学运算的函数,包括三角函数,算术运算的函数,复数处理函数等

三角函数

import numpy as np

a = np.array([0, 30, 45, 60, 90])
print("不同角度的正弦值:")
# 通过乘 pi/180 转化为弧度
print(np.sin(a * np.pi / 180))
print("\n")
print("数组中角度的余弦值:")
print(np.cos(a * np.pi / 180))
print("\n")
print("数组中角度的正切值:")
print(np.tan(a * np.pi / 180))
运行结果

不同角度的正弦值: [0. 0.5 0.70710678 0.8660254 1. ]

数组中角度的余弦值: [1.00000000e+00 8.66025404e-01 7.07106781e-01 5.00000000e-01 6.12323400e-17]

数组中角度的正切值: [0.00000000e+00 5.77350269e-01 1.00000000e+00 1.73205081e+00 1.63312394e+16]

舍入函数

numpy.around(a,decimals)
参数描述
a数组
decimals舍入的小数位数。 默认值为0。 如果为负,整数将四舍五入到小数点左侧的位置
import numpy as np

a = np.array([1.0, 5.55, 123, 0.567, 25.532])
print("原数组:")
print(a)
print("\n")
print("舍入后:")
print(np.around(a))
print(np.around(a, decimals=1))
print(np.around(a, decimals=-1))
运行结果

原数组: [ 1. 5.55 123. 0.567 25.532]

舍入后: [ 1. 6. 123. 1. 26.] [ 1. 5.6 123. 0.6 25.5] [ 0. 10. 120. 0. 30.]

import numpy as np

a = np.array([0.8, 16.35])
print(np.around(a))
print(np.around(a, decimals=-1))
运行结果

[ 1. 16.] [ 0. 20.]

numpy.floor()

  • numpy.floor() 返回小于或者等于指定表达式的最大整数,即向下取整
import numpy as np

a = np.array([-1.7, 1.5, -0.2, 0.6, 10])
print("提供的数组:")
print(a)
print("\n")
print("修改后的数组:")
print(np.floor(a))
运行结果

提供的数组: [-1.7 1.5 -0.2 0.6 10. ]

修改后的数组: [-2. 1. -1. 0. 10.]

numpy.ceil()

  • numpy.ceil() 返回大于或者等于指定表达式的最小整数,即向上取整
import numpy as np

a = np.array([-9.8, 10.37, 205.9])
print(np.floor(a))
print(np.ceil(a))
运行结果

[-10. 10. 205.] [ -9. 11. 206.]

算术运算

  • NumPy 算术函数包含简单的加减乘除: add()subtract()multiply()divide()
  • 需要注意的是数组必须具有相同的形状或符合数组广播规则
  • 此外 Numpy 也包含了其他重要的算术函数

numpy.reciprocal()

  • numpy.reciprocal() 函数返回参数逐元素的倒数。如 1/4 倒数为 4/1
import numpy as np

a = np.array([0.25, 1.33, 1, 100])
print("我们的数组是:")
print(a)
print("调用 reciprocal 函数:")
print(np.reciprocal(a))
运行结果

我们的数组是: [ 0.25 1.33 1. 100. ] 调用 reciprocal 函数: [4. 0.7518797 1. 0.01 ]

import numpy as np

b = np.array([2.5, 1, 0, 100], dtype=int)
print(np.reciprocal(b))
运行结果

[0 1 inf 0] # inf 表示无穷

numpy.power()

  • numpy.power() 函数将第一个输入数组中的元素作为底数,计算它与第二个输入数组中相应元素的幂
import numpy as np

a = np.array([10, 100, 1000])
print("我们的数组是;")
print(a)
print("调用 power 函数:")
print(np.power(a, 2))
print("第二个数组:")
b = np.array([1, 2, 3])
print(b)
print("再次调用 power 函数:")
print(np.power(a, b))
运行结果

我们的数组是; [ 10 100 1000] 调用 power 函数: [ 100 10000 1000000] 第二个数组: [1 2 3] 再次调用 power 函数: [ 10 10000 1000000000]

numpy.mod()

  • numpy.mod() 计算输入数组中相应元素的相除后的余数。函数 numpy.remainder() 也产生相同的结果
import numpy as np

a = np.array([10, 20, 30])
b = np.array([2, 8, 9])
print("调用 mod() 函数:")
print(np.mod(a, b))
运行结果

调用 mod() 函数: [0 4 3]

统计函数

  • NumPy 提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差和方差等

numpy.amin() 和 numpy.amax()

  • numpy.amin() 用于计算数组中的元素沿指定轴的最小值
  • numpy.amax() 用于计算数组中的元素沿指定轴的最大值
import numpy as np

a = np.array([[3, 7, 5], [8, 4, 3], [2, 4, 9]])
print("我们的数组是:")
print(a)
print("\n")
print("调用 amin() 函数:")
print(np.amin(a, 1))  # 1 表示轴1,即横轴
print("\n")
print("再次调用 amin() 函数:")
print(np.amin(a, 0))  # 0 表示轴0,即纵轴
print("\n")
print("调用 amax() 函数:")
print(np.amax(a))  # 不加参数表示数组整体元素的最大值
print("\n")
print("再次调用 amax() 函数:")
print(np.amax(a, axis=0))
运行结果

我们的数组是: [[3 7 5] [8 4 3] [2 4 9]]

调用 amin() 函数: [3 3 2]

再次调用 amin() 函数: [2 4 3]

调用 amax() 函数: 9

再次调用 amax() 函数: [8 7 9]

numpy.ptp()

  • numpy.ptp() 函数计算数组中元素最大值与最小值的差(最大值 - 最小值)
import numpy as np

a = np.array([[3, 7, 5], [8, 4, 3], [2, 4, 9]])
print("我们的数组是:")
print(a)
print("\n")
print("调用 ptp() 函数:")
print(np.ptp(a))
print("\n")
print("沿轴 1 调用 ptp() 函数:")
print(np.ptp(a, axis=1))
print("\n")
print("沿轴 0 调用 ptp() 函数:")
print(np.ptp(a, axis=0))
运行结果

我们的数组是: [[3 7 5] [8 4 3] [2 4 9]]

调用 ptp() 函数: 7

沿轴 1 调用 ptp() 函数: [4 5 7]

沿轴 0 调用 ptp() 函数: [6 3 6]

numpy.percentile()

  • 百分位数是统计中使用的度量,表示小于这个值的观察值的百分比
import numpy as np

a = np.array([[30, 40, 70], [80, 20, 10], [50, 90, 60]])
print("我们的数组是:")
print(a)

print("调用 percentile() 函数:")
print(np.percentile(a, 50))
print("沿轴 1 调用 percentile() 函数:")
print(np.percentile(a, 50, axis=1))
print("沿轴 0 调用 percentile() 函数:")
print(np.percentile(a, 50, axis=0))
运行结果

我们的数组是: [[30 40 70] [80 20 10] [50 90 60]] 调用 percentile() 函数: 50.0 沿轴 1 调用 percentile() 函数: [40. 20. 60.] 沿轴 0 调用 percentile() 函数: [50. 40. 60.]

numpy.median()

  • numpy.median() 函数用于计算数组 a 中元素的中位数(中值)

numpy.mean()

  • numpy.mean() 函数返回数组中元素的算术平均值,如果提供了轴,则沿其计算
  • 算术平均值是沿轴的元素的总和除以元素的数量

numpy.average()

  • numpy.average() 函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值

标准差

  • 标准差是一组数据平均值分散程度的一种度量
  • 标准差是方差的算术平方根
std = sqrt(mean((x - x.mean())**2))

方差

  • 统计中的方差(样本方差)是每个样本值与全体样本值的平均数之差的平方值的平均数
  • 标准差是方差的平方根
mean((x - x.mean())** 2)

排序、搜索和计数函数

numpy.sort()

numpy.sort(a, axis, kind, order)
参数描述
a要排序的数组
axis沿着它排序数组的轴,如果没有数组会被展开,沿着最后的轴排序, axis=0 按列排序,axis=1 按行排序
kind默认为'quicksort'(快速排序),还有 'mergesort' (归并排序)和 'heapsort'(堆排序)
order如果数组包含字段,则是要排序的字段
import numpy as np

a = np.array([[3, 7], [9, 1]])
print("我们的数组是:")
print(a)
print("\n")
print("调用 sort() 函数:")
print(np.sort(a))
print("\n")
print("按列排序:")
print(np.sort(a, axis=0))
print("\n")
# 在 sort 函数中排序字段
dt = np.dtype([("name", "S10"), ("age", int)])
a = np.array([("raju", 21), ("anil", 25), ("ravi", 17), ("amar", 27)], dtype=dt)
print("我们的数组是:")
print(a)
print("\n")
print("按 name 排序:")
print(np.sort(a, order="name"))
运行结果

我们的数组是: [[3 7] [9 1]]

调用 sort() 函数: [[3 7] [1 9]]

按列排序: [[3 1] [9 7]]

我们的数组是: [(b'raju', 21) (b'anil', 25) (b'ravi', 17) (b'amar', 27)]

按 name 排序: [(b'amar', 27) (b'anil', 25) (b'raju', 21) (b'ravi', 17)]

numpy.argsort()

  • numpy.argsort() 函数返回的是数组值从小到大的索引值
import numpy as np

x = np.array([3, 1, 2])
print("我们的数组是:")
print(x)
print("\n")
print("对 x 调用 argsort() 函数:")
y = np.argsort(x)
print(y)
print("\n")
print("以排序后的顺序重构原数组:")
print(x[y])
print("\n")
print("使用循环重构原数组:")
for i in y:
    print(x[i], end=" ")
运行结果

我们的数组是: [3 1 2]

对 x 调用 argsort() 函数: [1 2 0]

以排序后的顺序重构原数组: [1 2 3]

使用循环重构原数组: 1 2 3

numpy.lexsort()

  • numpy.lexsort() 用于对多个序列进行排序
  • 把它想象成对电子表格进行排序,每一列代表一个序列,排序时优先照顾靠后的列
import numpy as np

nm = ("raju", "anil", "ravi", "amar")
dv = ("f.y.", "s.y.", "s.y.", "f.y.")
ind = np.lexsort((dv, nm))
print("调用 lexsort() 函数:")
print(ind)
print("\n")
print("使用这个索引来获取排序后的数据:")
print([nm[i] + ", " + dv[i] for i in ind])
运行结果

调用 lexsort() 函数: [3 1 0 2]

使用这个索引来获取排序后的数据: ['amar, f.y.', 'anil, s.y.', 'raju, f.y.', 'ravi, s.y.']

numpy.argmax() 和 numpy.argmin()

  • numpy.argmax() 和 numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引

其他函数

函数描述
numpy.nonzero()返回输入数组中非零元素的索引
numpy.where()返回输入数组中满足给定条件的元素的索引
numpy.extract()根据某个条件从数组中抽取元素,返回满条件的元素

字节交换

在几乎所有的机器上,多字节对象都被存储为连续的字节序列。字节顺序,是跨越多字节的程序对象的存储规则

  • **大端模式:**指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
  • **小端模式:**指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

numpy.ndarray.byteswap()

  • numpy.ndarray.byteswap() 函数将 ndarray 中每个元素中的字节进行大小端转换
import numpy as np

a = np.array([1, 256, 8755], dtype=np.int16)
print("我们的数组是:")
print(a)
print("以十六进制表示内存中的数据:")
print(map(hex, a))
# byteswap() 函数通过传入 true 来原地交换
print("调用 byteswap() 函数:")
print(a.byteswap(True))
print("十六进制形式:")
print(map(hex, a))
# 我们可以看到字节已经交换了
运行结果

我们的数组是: [ 1 256 8755] 以十六进制表示内存中的数据:

<map object at 0x000002324ECB6140> 调用 byteswap() 函数: [ 256 1 13090] 十六进制形式: <map object at 0x00000232365C6D40>

副本和视图

  • 在执行函数时,其中一些返回输入数组的副本,而另一些返回视图
  • 当内容物理存储在另一个位置时,称为副本
  • 如果提供了相同内存内容的不同视图,就将其称为视图

无复制

  • 简单的赋值不会创建数组对象的副本。
  • 相反,它使用原始数组的相同id()来访问它。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。
import numpy as np

a = np.arange(6)
print("我们的数组是:")
print(a)
print("调用 id() 函数:")
print(id(a))
print("a 赋值给 b:")
b = a
print(b)
print("b 拥有相同 id():")
print(id(b))
print("修改 b 的形状:")
b.shape = 3, 2
print(b)
print("a 的形状也修改了:")
print(a)
运行结果

我们的数组是:

[0 1 2 3 4 5]

调用 id() 函数:

2693549430928

a 赋值给 b:

[0 1 2 3 4 5]

b 拥有相同 id():

2693549430928

修改 b 的形状:

[[0 1] [2 3] [4 5]]

a 的形状也修改了:

[[0 1] [2 3] [4 5]]

视图或浅拷贝

  • ndarray.view() 方会创建一个新的数组对象,该方法创建的新数组的维数变化不会改变原始数据的维数
import numpy as np

# 最开始 a 是个 3X2 的数组
a = np.arange(6).reshape(3, 2)
print("数组 a:")
print(a)
print("创建 a 的视图:")
b = a.view()
print(b)
print("两个数组的 id() 不同:")
print("a 的 id():")
print(id(a))
print("b 的 id():")
print(id(b))
# 修改 b 的形状,并不会修改 a
b.shape = 2, 3
print("b 的形状:")
print(b)
print("a 的形状:")
print(a)
运行结果

数组 a:

[[0 1] [2 3] [4 5]]

创建 a 的视图:

[[0 1] [2 3] [4 5]]

两个数组的 id() 不同:

a 的 id():

2045124909104

b 的 id():

2045534034832

b 的形状:

[[0 1 2] [3 4 5]]

a 的形状:

[[0 1] [2 3] [4 5]]

编辑于 2024/1/4 09:33:12