Как эффективно применять операции с условными выражениями, например if, к большому массиву numpy в python? - PullRequest
0 голосов
/ 03 января 2019

Добрый день всем, я помещал необработанные данные в числовые массивы, затем я хотел выполнить операции, как логарифм, основание 10, с "если" для этих массивов, тем не менее, эти числовые массивы слишком велики, и, следовательно, они принимают много времени для их завершения.

введите описание изображения здесь

x = [ 20*math.log10(i) if i>0 and 20*math.log10(i)>=-60 else (-(120+20*math.log10(abs(i))) if i<0 and 20*math.log10(abs(i))>=-60 else -60) for i in a3 ]

В предыдущем фрагменте кода я использовал один из массивов каналов, выброшенных из необработанных аудиоданных, "a3", и я создал другой массив, "x", который будет содержать массив для построения графика от -120 до 0, по краю у. Кроме того, как вы могли заметить, мне нужно было отделить положительные исходные элементы от массива numpy, чем отрицательные исходные элементы от массива numpy, а также 0 с -60 после операций 0. Имея этот последний график: введите описание изображения здесь

Проблема с этим кодом заключается в том, что, как я уже говорил, для завершения вычислений требуется примерно 10 секунд, и это только для 1 канала, и мне нужно вычислить 8 каналов, поэтому мне нужно подождать примерно 80 сек.

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

x = 20*numpy.log10(abs(a3))

Но я не нашел ничего, связанного с манипулированием настройками этой операции, numpy.log10, с помощью if, условных выражений или чего-то в этом роде. Мне действительно нужно идентифицировать отрицательные и положительные исходные значения, а также 0, и, очевидно, преобразовать 0 в -60, делая минимальный предел -60, и контрольную точку, как код, который я показал вам ранее.

Примечание: я уже пытался сделать это с помощью циклов, таких как "for" и "while", но это занимает намного больше времени, чем фактический метод, например, 14 секунд каждый.

Спасибо за ваши ответы !!

1 Ответ

0 голосов
/ 03 января 2019

Как правило, при публикации вопросов рекомендуется включать небольшой рабочий пример.Я знаю, что вы включили изображение ваших данных, но это сложно использовать другим, поэтому было бы лучше просто предоставить нам небольшой массив данных.Это важно, потому что решение часто зависит от данных.Например, все ваши данные (я думаю) между -1 и 1, так что журнал всегда отрицательный.Если это не так, то ваше решение может не сработать.

Нет необходимости проверять, если i>0, а затем применить abs, если i отрицательно.Это именно то, что применяет abs в первую очередь.

Как вы заметили, мы также можем использовать пустую векторизацию, чтобы избежать понимания списка.Обычно быстрее сделать что-то вроде np.sin(X), чем [ np.sin(x) for x in X].

Наконец, если вы делаете что-то вроде X>0 в numpy, он возвращает логический массив, в котором говорится, что каждый элемент >0.

Обратите внимание, что другим способом написания вашего понимания списка было бы сначала взять 20*math.log10(abs(i)) и заменить все значения <-60 на -60, а затем в любое место, где i<0, перевернуть данные о -60`.Мы можем сделать это в векторизованной операции.

-120*(a3<0)+np.sign(a3)*np.maximum(20*np.log10(np.abs(a3)),-60)

Вероятно, это можно немного оптимизировать, поскольку a3<0 и np.sign(a3) делают подобные вещи.Тем не менее, я почти уверен, что это быстрее, чем списки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...