我有一个自定义dtype my_type 的数组,我从二进制文件中成功读取了该数组。自定义dtype后面有一个标题部分。数据部分是 np.int16 数字,因此自定义dtype如下所示:
header, imaginary, real, imaginary, real, ..., imaginary, real
现在我正在寻找一种智能的方式来使用Numpy的视图来获取 np.complex64 仅数据的数组考虑到以下事实,没有复制/循环等:
即,从自定义dtype数组:
[my_type, my_type, ..., my_type]
我喜欢得到一个更大的数组:
[complex64, complex64, ..., complex64]
是否可以使用Numpy的视图一次性完成此操作?
更新
所以解决方案是在内存中复制。非常感谢下面的答案。但是因为恼人的标题出现在每个数据帧之前,所以似乎尽管在存储器中进行了复制,仍然需要在所有数据帧上进行循环。我以示意图的方式:
a = np.arange(10, dtype=np.float16)
skip_annoying_header = 2
r = np.zeros(a.size - skip_annoying_header, np.float16)
r[0::2], r[1::2] = a[skip_annoying_header + 1::2], a[skip_annoying_header::2]
r = r.astype(np.float32)
r = r.view(np.complex64)
我在每个数据框的for
循环中执行此操作,然后在for
循环结束时,我再次将r
的内容复制到大数组。
这种循环可以以某种方式消除吗?
答案 0 :(得分:3)
所有3个要求都与view
冲突。
忽略header
字段需要选择其他字段。选择单个字段显然是一个视图,但多个字段的状态是不断变化的。当我尝试除了简单地查看值之外的任何事情时,我会收到警告:
In [497]: dt=np.dtype('U10,f,f,f,f')
In [498]: x=np.zeros((5,),dt)
In [505]: x[['f1','f3']].__array_interface__
/usr/bin/ipython3:1: FutureWarning: Numpy has detected that you (may be) writing to an array returned
by numpy.diagonal or by selecting multiple fields in a record
array. This code will likely break in a future numpy release --
see numpy.diagonal or arrays.indexing reference docs for details.
The quick fix is to make an explicit copy (e.g., do
arr.diagonal().copy() or arr[['f0','f1']].copy()).
请记住,数据是逐个元素排列的,dtype元组值在紧凑块中 - 基本上是显示的紧凑版本。忽略header
需要跳过该组字节。 view
可以处理由strides
生成的跳过,但不能处理这些dtype字段跳过。
In [533]: x
Out[533]:
array([('header', 0.0, 5.0, 1.0, 10.0), ('header', 1.0, 4.0, 1.0, 10.0),
('header', 2.0, 3.0, 1.0, 10.0), ('header', 3.0, 2.0, 1.0, 10.0),
('header', 4.0, 1.0, 1.0, 10.0)],
dtype=[('f0', '<U10'), ('f1', '<f4'), ('f2', '<f4'), ('f3', '<f4'), ('f4', '<f4')])
要探索对复杂字段进行重新排序,请尝试使用二维数组:
In [509]: y=np.arange(10.).reshape(5,2) # 2 column float
In [510]: y.view(complex) # can be viewed as complex
Out[510]:
array([[ 0.+1.j],
[ 2.+3.j],
[ 4.+5.j],
[ 6.+7.j],
[ 8.+9.j]])
In [511]: y[:,::-1].view(complex)
...
ValueError: new type not compatible with array.
要切换real / imaginay列,我必须复制。 complex
要求2个浮点数是连续且有序的。
In [512]: y[:,::-1].copy().view(complex)
Out[512]:
array([[ 1.+0.j],
[ 3.+2.j],
[ 5.+4.j],
[ 7.+6.j],
[ 9.+8.j]])
float32
到float64
显然不是view
更改。一个使用每个数字4个字节,另一个8.您不能查看&#39; 4为8而不复制。
答案 1 :(得分:2)
@hpaulj绝对正确,这与视图冲突。
但是,你可能会问错误的问题。
numpy
当然可以做您想做的事情,但您需要在内存中制作临时副本。
总的来说,通过重新思考&#34;将整个文件读入内存然后查看它,可能会更好地满足您的需求。做法。而是寻找过去(或读入)标题,然后用fromfile
读入数据部分。不过,只要您不介意制作副本从float32
到float64
,就可以相对直接地将事情操作到您想要的内容中。 &#39; S
首先,让我们生成一个类似于你的文件:
import numpy as np
reals = np.arange(100).astype(np.float32)
imag = -9999.0 * np.ones(100).astype(np.float32)
data = np.empty(reals.size + imag.size, dtype=np.float32)
data[::2], data[1::2] = imag, reals
with open('temp.dat', 'wb') as outfile:
# Write a 1Kb header (of literal "x"'s, in this case)
outfile.write(1024 * 'x')
outfile.write(data)
现在我们将其阅读。
在使用seek
阅读数据之前,忽略标题的关键是fromfile
过去。
然后,我们可以解交织数据并同时转换为64位浮点数。
最后,您可以将生成的2xN长度float64
数组视为N长complex128
数组。 (注意:complex128
是复数的64位版本。complex64
是32位版本。)
例如:
import numpy as np
with open('temp.dat', 'rb') as infile:
# Seek past header
infile.seek(1024)
# Read in rest of file as float32's
data = np.fromfile(infile, dtype=np.float32)
result = np.empty(data.size, np.float64)
# De-interleave imag & real back into expected real & imag, converting to 64-bit
result[::2], result[1::2] = data[1::2], data[::2]
# View the result as complex128's (i.e. 64-bit complex numbers)
result = result.view(np.complex128)