的ndarray
是一个对象,在存储器提供一个python阵列接口到数据。
通常,您要使用数组查看的内存与运行Python的计算机的字节顺序不同。
例如,我可能正在使用低端CPU的计算机(例如Intel Pentium),但是我已经从由大端计算机编写的文件中加载了一些数据。假设我已经从Sun(big-endian)计算机编写的文件中加载了4个字节。我知道这4个字节代表两个16位整数。在big-endian计算机上,先存储两个字节的整数,然后再存储最高有效字节(MSB),然后存储最低有效字节(LSB)。因此,字节按存储顺序排列:
MSB整数1
LSB整数1
MSB整数2
LSB整数2
假设这两个整数实际上是1和770。因为770 = 256 * 3 + 2,所以内存中的4个字节将分别包含:0、1、3、2。我从文件中加载的字节将具有以下内容:
>>> big_end_buffer = bytearray([0,1,3,2])
>>> big_end_buffer
bytearray(b'\x00\x01\x03\x02')
我们可能要使用an ndarray
来访问这些整数。在这种情况下,我们可以在该内存周围创建一个数组,并告诉numpy有两个整数,它们是16位的big-endian:
>>> import numpy as np
>>> big_end_arr = np.ndarray(shape=(2,),dtype='>i2', buffer=big_end_buffer)
>>> big_end_arr[0]
1
>>> big_end_arr[1]
770
请注意dtype
上方的数组>i2
。的>
意思是“大端”(<
是小端)和i2
手段“签订2字节整数”。例如,如果我们的数据表示一个无符号的4字节小尾数整数,则dtype字符串将为<u4
。
实际上,我们为什么不尝试呢?
>>> little_end_u4 = np.ndarray(shape=(1,),dtype='<u4', buffer=big_end_buffer)
>>> little_end_u4[0] == 1 * 256**1 + 3 * 256**2 + 2 * 256**3
True
回到我们的big_end_arr
例子中-在这种情况下,我们的基础数据是big-endian(数据字节序),并且我们已将dtype设置为match(dtype也是big-endian)。但是,有时您需要将它们翻转。
警告
标量目前不包含字节顺序信息,因此从数组中提取标量将返回本机字节顺序的整数。因此:
>>> big_end_arr[0].dtype.byteorder == little_end_u4[0].dtype.byteorder
True
从介绍中可以想象,有两种方法可以影响数组的字节顺序与其查看的基础内存之间的关系:
更改数组dtype中的字节顺序信息,以使其将基础数据解释为不同的字节顺序。这是角色arr.newbyteorder()
更改基础数据的字节顺序,保持dtype解释不变。这是做什么的arr.byteswap()
。
您需要更改字节顺序的常见情况是:
您的数据和dtype的字节序不匹配,并且您想更改dtype使其与数据匹配。
您的数据和dtype的字节序不匹配,并且您想交换数据,使其与dtype匹配
您的数据和dtype的字节序匹配,但是您希望交换数据,并且dtype反映这一点
我们做一些他们不匹配的东西:
>>> wrong_end_dtype_arr = np.ndarray(shape=(2,),dtype='<i2', buffer=big_end_buffer)
>>> wrong_end_dtype_arr[0]
256
解决这种情况的明显方法是更改dtype,使其具有正确的字节序:
>>> fixed_end_dtype_arr = wrong_end_dtype_arr.newbyteorder()
>>> fixed_end_dtype_arr[0]
1
请注意,数组在内存中没有更改:
>>> fixed_end_dtype_arr.tobytes() == big_end_buffer
True
如果您需要对内存中的数据进行某种排序,则可能需要这样做。例如,您可能正在将内存写出到需要特定字节顺序的文件中。
>>> fixed_end_mem_arr = wrong_end_dtype_arr.byteswap()
>>> fixed_end_mem_arr[0]
1
现在,数组已在内存中更改:
>>> fixed_end_mem_arr.tobytes() == big_end_buffer
False
您可能具有正确指定的数组dtype,但是您需要使数组在内存中具有相反的字节顺序,并且希望dtype匹配,以便数组值有意义。在这种情况下,您只需执行上述两个操作即可:
>>> swapped_end_arr = big_end_arr.byteswap().newbyteorder()
>>> swapped_end_arr[0]
1
>>> swapped_end_arr.tobytes() == big_end_buffer
False
使用ndarray astype方法可以更简单地将数据转换为特定的dtype和字节顺序:
>>> swapped_end_arr = big_end_arr.astype('<i2')
>>> swapped_end_arr[0]
1
>>> swapped_end_arr.tobytes() == big_end_buffer
False