内存块
array切片之所以可以对原array数据进行修改,是因为两个array的内存地址在一个地方
import numpy as np
x = np.array(range(1,5))
y = x[:-1]
x[0] = 9
# 查看array的内存地址
x.__array_interface__['data'][0],y.__array_interface__['data'][0]
# 结果 => (1713365532096, 1713365532096)
通过.flags
可以查看出x
与 y
哪个是原始array哪个是切片
x.flags
""" 结果
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True # 原始数据拥有数据
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
"""
y.flags
""" 结果
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : False # 切片不拥有数据
WRITEABLE : True # 但是同样可以修改数据
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
"""
数据类型
dtype
存在的几个属性
np.dtype(np.int8).type # 元素数据类型<class 'numpy.int8'>
np.dtype(np.int8).itemsize # 一个元素占内存字节大小 1
dtype
astype
类型改变 及运算后改变
以及不改变dtype
的运算办法
x = np.array(range(1,5), dtype = np.float)
y = x.astype(np.int8)
# 变成浮点型
a = y+1.0
print(a.dtype) # float64
# 以大的dtype类型为最后就
m = y + np.array([256], dtype=np.int32)
print(m.dtype) # int32
# 不改变dtype的运算办法
y[:] = y + 1.5 # 向下取整
print(y, y.dtype) # [2 3 4 5] int8
不常用,但效率挺高的
dtype
转换方法,直接2进制转换
x = np.array([1,2,3,4], dtype=np.uint8)
x.__array_interface__['data'][0] # 1713370045744
bytes(x) # b'\x01\x02\x03\x04'
print(x) # [1 2 3 4]
"""
给dtype 直接赋值 '<i1' int8 '<i2' int16
i <=> 8,i1 <=> int 8*1
"""
x.dtype = '<i2' # int16
x.__array_interface__['data'][0] # 1713370045744
bytes(x) # b'\x01\x02\x03\x04'
print(x) # [ 513 1027]
array的内存地址没变,直接二进制编码转换成,最后显示的array结果不一样。
创建视图
创建视图的时候同样可以用指定dtype
类型的办法执行
y = x.view('<i4')
y.__array_interface__['data'][0] # 1713370045744
# 视图的内存地址依旧和 x 相同,所以修改原数值,y 也会变化
print(y) # array([67305985])
x[1] = 5
print(y) # array([328193])
# 同样修改视图 y , x 也会变化
y[0] = 1024
print(y.dtype) # int32
print(x, x.dtype) # [1024 0] int16
y.base is x # True
索引
-
索引的本质:
- 根据步伐查找位置
x = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]], dtype = np.int8)
# 步伐 大小与dtype有关
x.strides # (3, 1)
byte_offset = sum(x.strides*np.array([1,2])) # 步伐*想要查找的位置
x.flat[byte_offset] # 6
x[1, 2] # 6
用步长改变维度
from numpy.lib.stride_tricks import as_strided
x = np.array([1, 2, 3, 4, 5, 6], dtype = np.int16)
# 维度 3行 2列
shape = (3, 2)
# 第一个维度间隔2个元素,第二个维度间隔1个元素
strides = x.itemsize*np.array([2, 1])
y = as_strided(x, shape = shape, strides = strides)
print(y)
""" 结果
array([[1, 2],
[3, 4],
[5, 6]], dtype=int16)
"""
上面的例子并不能看出该方法的优势,将数组维度和量增多时
from numpy.lib.stride_tricks import as_strided
# 生成9*9的数组
## 采用np.int8 a.itemsize = 1 便于操作步伐strides
a = np.array(range(1,10),dtype=np.int8)
b = as_strided(a, shape=(9, 9), strides = (0,1)).copy() # 第一维度步伐为0,即相等
## 将 9*9 转化成 3*3*3*3 数组 ==直接在原array上切割==
shape = (3, 3, 3, 3)
"""
第一维度(数组间行)间隔 3*(3*3)个元素, 第二维度(数组间列)间隔3个维度
第三维度(数组内行)间隔3个元素,最后的维度(数组内列)间隔1个元素
"""
strides = b.itemsize*np.array([27, 3 , 9, 1])
out = as_strided(b, shape=shape , strides = strides)
array([[[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[4, 5, 6],
[4, 5, 6],
[4, 5, 6]],
[[7, 8, 9],
[7, 8, 9],
[7, 8, 9]]],
[[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[4, 5, 6],
[4, 5, 6],
[4, 5, 6]],
[[7, 8, 9],
[7, 8, 9],
[7, 8, 9]]],
[[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[4, 5, 6],
[4, 5, 6],
[4, 5, 6]],
[[7, 8, 9],
[7, 8, 9],
[7, 8, 9]]]], dtype=int8)