2015-05-30 4 views
0

У меня есть то, что, как я думал, будет простой задачей в numpy, но у меня проблемы.Создайте массив numpy из функции python

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

Я нашел numpy.fromfunction, но он не ведет себя дистанционно, как предлагает documentation. Это, кажется, «vectorise» функция, которая означает, что вместо передачи фактических индексов она проходит Numpy массив индексов: (. Если мы будем использовать отладчик для проверки i, это numpy.array экземпляр)

def vsin(i): 
    return float(round(A * math.sin((2 * pi * wf) * i))) 

numpy.fromfunction(vsin, (len,), dtype=numpy.int16) 
# TypeError: only length-1 arrays can be converted to Python scalars 

Таким образом, если мы будем пытаться использовать NumPy-х vectorised sin функции:

def vsin(i): 
    return (A * numpy.sin((2 * pi * wf) * i)).astype(numpy.int16) 

numpy.fromfunction(vsin, (len,), dtype=numpy.int16) 

мы не получаем ошибку типа, но если len > 2**15 мы получаем разрывы разделочной accross нашего осциллятора, потому что numpy использует int16_t для представления индекса!

В частности, речь идет не о sin: Я хочу иметь возможность писать произвольные функции python, подобные этому (независимо от того, существует ли версия с числовым вектором или нет) и иметь возможность запускать их внутри жесткой петли C (скорее чем окольный питон один), и не нужно беспокоиться о целочисленном wraparound.

Должен ли я писать собственное расширение для cython, чтобы иметь возможность сделать это? У numpy есть поддержка для запуска функций python один раз за элемент в массиве с доступом к индексу?

Это не должно быть функцией создания: я могу использовать numpy.empty (или, действительно, повторно использовать существующий массив из другого места.) Таким образом, также была бы реализована векторная функция преобразования.

+0

FYI, на данный момент я просто запускаю цикл python, который не слишком медленен для небольших массивов, с которыми я имею дело первоначально. – tehwalrus

+0

Почему вы не используете что-то вроде 'vsin (np.arange (1000))' или 'vsin (np.linspace (0,4,100)'? Посмотрите на код 'fromfunction'. Все, что он делает, это' vsin (np. индексы ({len,)) '. Если' индексы' не дают правильных значений 'i', не используйте их. – hpaulj

ответ

0

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

Если вы используете 2-байтовое целое число и попытаться создать массив целочисленных значений в диапазоне от 0 до 32767, вы получите ошибку обхода. Массив будет выглядеть следующим образом:

[0, 1, 2, ... , 32767, -32768, -32767, ...] 

Самое простое решение, предполагая память не слишком плотно, чтобы использовать больше байт для целого массива, порожденного fromfunction, так что вы не должны обернуть вокруг проблемы в первом место (до нескольких миллиардов):

numpy.fromfunction(vsin, (len,), dtype=numpy.int32) 

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

+0

Спасибо за ваш ответ.Я не пытаюсь представить в моем массиве значения, большие, чем INT16_MAX, но массив будет длиннее INT16_MAX. С Cython я могу написать функцию, которая использует итератор C, а не python, что ускоряет такие задания. Я предположил, что numpy будет иметь что-то подобное встроенное, но я, по-видимому, ошибался. – tehwalrus

Смежные вопросы