Можно ли создать numpy.ndarray, который содержит сложные целые числа?

Я хотел бы создать numpy.ndarray объекты, которые содержат сложные целочисленные значения в них. NumPy имеет комплексную встроенную поддержку, но для форматов с плавающей запятой (float а также double) только; Я могу создать ndarray с dtype='cfloat', например, но нет аналога dtype='cint16', Я хотел бы иметь возможность создавать массивы, которые содержат сложные значения, представленные с использованием 8- или 16-битных целых чисел.

Я нашел этот список рассылки с 2007 года, где кто-то спрашивал о такой поддержке. Единственный обходной путь, который они рекомендовали, заключался в определении нового dtype который содержит пары целых чисел. Кажется, это представляет каждый элемент массива как кортеж из 2 значений, но не ясно, какую другую работу нужно будет выполнить, чтобы заставить полученный тип данных беспрепятственно работать с арифметическими функциями.

Я также рассмотрел другой подход, основанный на регистрации пользовательских типов в NumPy. У меня нет проблем с переходом на C API, чтобы настроить его, если он будет работать хорошо. Тем не менее, документация для структуры дескриптора типа, кажется, предполагает, что тип kind Поле поддерживает только целые числа со знаком / без знака, числа с плавающей точкой и сложные числовые типы с плавающей точкой. Не ясно, что я смог бы получить что угодно, пытаясь определить сложный целочисленный тип.

Какие-нибудь рекомендации относительно подхода, который может работать?

Изменить: еще одна вещь; Какую бы схему я ни выбрал, она должна быть способна оборачивать существующие сложные целочисленные буферы без выполнения копирования. То есть я хотел бы иметь возможность использовать PyArray_SimpleNewFromData() выставить буфер в Python без необходимости сначала делать копию буфера. Буфер будет уже в реальном / мнимом формате с чередованием и будет либо массивом int8_t или же int16_t,

2 ответа

Решение

Я также имею дело со множеством сложных целочисленных данных, как правило, с базовыми данными. я использую

dtype = np.dtype([('re', np.int16), ('im', np.int16)])

Это не идеально, но адекватно описывает данные. Я использую его для загрузки в память, не удваивая размер данных. Он также имеет преимущество в возможности прозрачной загрузки и хранения с HDF5.

DATATYPE  H5T_COMPOUND {
    H5T_STD_I16LE "re";
    H5T_STD_I16LE "im";
}

Использовать это просто, просто по-другому.

x = np.zeros((3,3),dtype)
x[0,0]['re'] = 1
x[0,0]['im'] = 2
x
>> array([[(1, 2), (0, 0), (0, 0)],
>>        [(0, 0), (0, 0), (0, 0)],
>>        [(0, 0), (0, 0), (0, 0)]], 
>>  dtype=[('re', '<i2'), ('im', '<i2')])

Чтобы сделать с ним математику, я конвертирую в собственный сложный тип с плавающей точкой. Очевидный подход не работает, но это не так сложно.

y = x.astype(np.complex64) # doesn't work, only gets the real part
y = x['re'] + 1.j*x['im']  # works, but slow and big
y = x.view(np.int16).astype(np.float32).view(np.complex64)
y
>> array([[ 1.+2.j,  0.+0.j,  0.+0.j],
>>        [ 0.+0.j,  0.+0.j,  0.+0.j],
>>        [ 0.+0.j,  0.+0.j,  0.+0.j]], dtype=complex64)

Этот последний подход к конверсии вдохновлен /questions/6445433/kakoj-samyij-byistryij-sposob-preobrazovat-massiv-chereduyuschihsya-chisel-numpy-v-complex64/6445444#6445444

Рассматривали ли вы использование матриц вида [[a,-b],[b,a]] в качестве замены комплексных чисел? Обычное умножение и сложение матриц соответствует сложению или умножению комплексных чисел (это подкольцо набора матриц 2x2 изоморфно комплексным числам). Я думаю, что python может обрабатывать целочисленную матричную алгебру.

Python и, следовательно, Numpy поддерживает комплексные числа, если вам нужны сложные целые числа, просто используйте np.round или игнорируйте десятичную часть.

например

import numpy as np
#Create 100 complex numbers in a 1D array
a=100*np.random.sample(100)+(100*np.random.sample(100)*1j)
#Reshape to a 2D array
np.round(a)
a.reshape(10,10)

#Get the real and imag parts of a couple x/y points as integers
print int(a[1:2].real)
print int(a[3:4].imag)
Другие вопросы по тегам