Numpy: Создание сложного массива из 2-х реальных? - PullRequest
53 голосов
/ 08 апреля 2010

Клянусь, это должно быть так просто ... Почему это не так?: (

На самом деле, я хочу объединить 2 части одного массива в сложный массив:

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

Ответы [ 8 ]

63 голосов
/ 08 апреля 2010

Это похоже на то, что вы хотите:

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]

PS : Если вы хотите сохранить память (без промежуточного массива):

result = 1j*Data[...,1]; result += Data[...,0]

devS 'решение ниже также быстро.

35 голосов
/ 05 сентября 2012

Там, конечно, довольно очевидно:

Data[...,0] + 1j * Data[...,1]
20 голосов
/ 24 февраля 2014

Если ваши действительные и мнимые части представляют собой срезы по последнему измерению, а ваш массив является смежным по последнему измерению, вы можете просто сделать

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]

Это работает, потому что в памяти комплексное число на самом деле представляет собой просто два числа с плавающей запятой.Первое представляет реальную часть, а второе представляет мнимую часть.Метод представления массива изменяет тип d массива, чтобы отразить, что вы хотите обрабатывать два смежных значения с плавающей запятой как одно комплексное число, и соответствующим образом обновляет измерение.

Этот метод не копирует никаких значений вмассив или выполнять любые новые вычисления, все, что он делает, это создает новый объект массива, который по-разному просматривает один и тот же блок памяти.Это позволяет выполнять эту операцию на намного быстрее, чем все, что связано с копированием значений.Это также означает, что любые изменения, внесенные в массив с комплексным значением, будут отражены в массиве с действительными и мнимыми частями.

Также может быть немного сложнее восстановить исходный массив, если удалить дополнительную осьто есть сразу после приведения типа.Такие вещи, как A_comp[...,np.newaxis].view(np.float64), в настоящее время не работают, потому что, на момент написания этой статьи, NumPy не обнаруживает, что массив все еще является C-смежным, когда добавляется новая ось.См. этот выпуск .A_comp.view(np.float64).reshape(A.shape), кажется, работает в большинстве случаев.

13 голосов
/ 06 января 2014

Это то, что вы ищете:

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])
9 голосов
/ 28 октября 2013

Я новичок в 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)
3 голосов
/ 12 марта 2017
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)
0 голосов
/ 15 августа 2018

Если вы действительно хотите повысить производительность (с большими массивами), можно использовать NumberxPR , который использует преимущества нескольких ядер.

Настройка:

>>> 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)
0 голосов
/ 18 июля 2011

Это сработало для меня:

вход:

[complex(a,b) for a,b in zip([1,2,3],[1,2,3])]

выход:

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