Python Numpy:从2个真实数组创建一个复杂数组?

Python Numpy:从2个真实数组创建一个复杂数组?,python,arrays,numpy,complex-numbers,Python,Arrays,Numpy,Complex Numbers,我想将同一数组的两个部分组合成一个复杂数组: Data[:,:,:,0] , Data[:,:,:,1] 这些不起作用: x = np.complex(Data[:,:,:,0], Data[:,:,:,1]) x = complex(Data[:,:,:,0], Data[:,:,:,1]) 我错过什么了吗?numpy不喜欢对复数执行数组函数吗?以下是错误: TypeError: only length-1 arrays can be converted to Python scalars

我想将同一数组的两个部分组合成一个复杂数组:

Data[:,:,:,0] , Data[:,:,:,1]
这些不起作用:

x = np.complex(Data[:,:,:,0], Data[:,:,:,1])
x = complex(Data[:,:,:,0], Data[:,:,:,1])
我错过什么了吗?numpy不喜欢对复数执行数组函数吗?以下是错误:

TypeError: only length-1 arrays can be converted to Python scalars

这似乎是你想要的:

numpy.apply_along_axis(lambda args: [complex(*args)], 3, Data)
下面是另一个解决方案:

# The ellipsis is equivalent here to ":,:,:"...
numpy.vectorize(complex)(Data[...,0], Data[...,1])
Data[...,0] + 1j * Data[...,1]
还有一个更简单的解决方案:

# The ellipsis is equivalent here to ":,:,:"...
numpy.vectorize(complex)(Data[...,0], Data[...,1])
Data[...,0] + 1j * Data[...,1]
PS:如果要保存内存(无中间数组):

下面的开发人员解决方案也很快。

对我来说很有效:

输入:

[complex(a,b) for a,b in zip([1,2,3],[1,2,3])]
[(1+4j), (2+5j), (3+6j)]
输出:

[complex(a,b) for a,b in zip([1,2,3],[1,2,3])]
[(1+4j), (2+5j), (3+6j)]

当然,有一个相当明显的问题:

Data[...,0] + 1j * Data[...,1]

我是python新手,所以这可能不是最有效的方法,但是,如果我正确理解了问题的意图,下面列出的步骤对我很有用

>>> import numpy as np
>>> Data = np.random.random((100, 100, 1000, 2))
>>> result = np.empty(Data.shape[:-1], dtype=complex)
>>> result.real = Data[...,0]; result.imag = Data[...,1]
>>> print Data[0,0,0,0], Data[0,0,0,1], result[0,0,0]
0.0782889873474 0.156087854837 (0.0782889873474+0.156087854837j)

这就是您要寻找的:

from numpy import array

a=array([1,2,3])
b=array([4,5,6])

a + 1j*b

->array([ 1.+4.j,  2.+5.j,  3.+6.j])

如果您的实部和虚部是沿最后一个维度的切片,并且您的数组沿最后一个维度是连续的,那么您可以这样做

A.view(dtype=np.complex128)
如果您使用的是单精度浮点,则

A.view(dtype=np.complex64)
这里有一个更完整的例子

import numpy as np
from numpy.random import rand
# Randomly choose real and imaginary parts.
# Treat last axis as the real and imaginary parts.
A = rand(100, 2)
# Cast the array as a complex array
# Note that this will now be a 100x1 array
A_comp = A.view(dtype=np.complex128)
# To get the original array A back from the complex version
A = A.view(dtype=np.float64)
如果您想消除铸件留下的额外尺寸,可以执行以下操作

A_comp = A.view(dtype=np.complex128)[...,0]
这是因为,在内存中,复数实际上只是两个浮点数。第一个代表实部,第二个代表虚部。 数组的view方法更改数组的数据类型,以反映您希望将两个相邻的浮点值视为单个复数,并相应地更新维度

此方法不会复制数组中的任何值或执行任何新计算,它所做的只是创建一个新的数组对象,以不同的方式查看同一内存块。 这使得该操作的执行速度比任何涉及复制值的操作都要快。 这也意味着在复数数组中所做的任何更改都将反映在具有实部和虚部的数组中

如果在类型转换之后立即移除额外的轴,则恢复原始阵列也可能有点困难。 像
A_comp[…,np.newaxis].view(np.float64)
这样的东西目前不起作用,因为在撰写本文时,NumPy没有检测到在添加新轴时数组仍然是C连续的。 看见
A_comp.view(np.float64)。重塑(A.shape)
似乎在大多数情况下都能正常工作。

如果您真的想提高性能(使用大阵列),可以使用它,它可以利用多核

import numpy as np

n = 51 #number of data points
# Suppose the real and imaginary parts are created independently
real_part = np.random.normal(size=n)
imag_part = np.random.normal(size=n)

# Create a complex array - the imaginary part will be equal to zero
z = np.array(real_part, dtype=complex)
# Now define the imaginary part:
z.imag = imag_part
print(z)
设置:

>>> import numpy as np
>>> Data = np.random.randn(64, 64, 64, 2)
>>> x, y = Data[...,0], Data[...,1]
使用
numexpr

>>> import numexpr as ne
>>> %timeit result = ne.evaluate("complex(x, y)")
573 µs ± 21.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
与快速numpy方法相比:

>>> %timeit result = np.empty(x.shape, dtype=complex); result.real = x; result.imag = y
1.39 ms ± 5.74 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我使用以下方法:

import numpy as np

real = np.ones((2, 3))
imag = 2*np.ones((2, 3))

complex = np.vectorize(complex)(real, imag)
# OR
complex = real + 1j*imag

恐怕也是这个错误:TypeError:只有length-1数组才能转换为PythonScalars@Duncan:我在执行测试后更新了原始答案。它现在似乎起作用了。非常感谢,确实起作用了。但是它非常慢(正如您可能期望的那样,因为它不是真正的numpy函数),现在每个循环需要5秒,而不是0秒。1@Duncan当前位置我添加了两个其他解决方案:也值得花时间来解决它们。如果这对你有用的话,请把答案翻出来!太好了,他们都快多了:)有趣的主意。但是,问题是如何组合
数据[:,:,:,0]
数据[:,:,:,1]
(比
a
更复杂)。另外,您应该使用更快更合适的
empty()
,而不是使用
zeros()
。我将其与数据[…,0]+1j*数据[…,1]解决方案进行了比较。数据=random.rand(1001000,2),c=0(a.shape[:-1],dtype=complex);c、 实数=数据[…,0];c、 imag=数据[…,1];比直接数据[…,0]+1j*数据[…,1]快2倍。令人惊讶的是,使用空而不是零的效果可以忽略不计。注:我得到的速度与我上一个答案相同:
result=1j*Data[…,1];结果+=数据[…,0]
。不过,如果不使用一个公式,这个答案就更自然了。我认为这是最好的答案,因为阅读代码的意图是显而易见的;Eric的答案虽然在功能上是正确的,但在阅读代码时就不那么清晰了。+1:非常清楚地解释了该方法的局限性。你可能想明确地增加另一个限制(在
A_comp
A
之间共享内存),以及这种方法的优势(速度)。这只是早期答案的部分重复,比如Pierre GM或我的答案:我认为它的唯一效果是花费人们的时间几乎没有附加值(超出示例),所以我建议你删除它。14个人不同意!虽然深度很弱,不值得打勾,但这个例子让我以最快的速度实现了我所需要的。你正在创建一个列表,而不是一个numpy数组