#numpy
#numpy
Вопрос:
У меня есть довольно сложная функция, скажем:
def func(elem):
// blah blah blah
return True
// blah blah blah
return False
Я хочу использовать функцию numpy.where() в соответствии с
arr2 = np.where(func(arr1), arr1, 0)
Но когда я пробую этот синтаксис и отлаживаю, я вижу func
, что передается весь массив, а не отдельные элементы. Типичные варианты использования, которые я вижу в документации / примерах, основаны только на простых компараторах, таких как arr < 5
, но мне нужно что-то более причудливое, что я не хочу пытаться писать в одной строке.
Если это возможно, или если есть какая-то векторизованная замена (акцент на эффективности), любые идеи приветствуются.
Комментарии:
1. Передается весь массив, потому что вы предоставляете весь массив в качестве входного аргумента. Одно из решений заключается в том, чтобы ваша функция перебирала входной массив и возвращала другой массив того же размера.
Ответ №1:
Я понял, как это сделать, используя np.vectorize
, за которым следует a list comprehension
, not np.where
. Возможно, из этого можно найти способ использовать numpy, а не для понимания списка.
func_vec = np.vectorize(func)
[arr1 if cond else 0 for cond in func_vec(arr1)]
В любом случае, используя func_vec(arr1)
вы получаете значения True / False для каждого элемента.
Примечание: если вам нужен новый массив типа arr1
, заменяющий на 0 элементы, которые возвращают False в вашей функции, то это должно сработать:
arr2 = np.where(func_vec(arr1), arr1, 0)
Редактировать:
Действительно, np.vectorize
не оптимизирован для производительности (по bad), по сути, является циклом for под капотом. Поэтому я бы рекомендовал попытаться написать вашу функцию векторизованным способом, а не пытаться векторизовать ее после этого.
Например, попробуйте преобразовать функцию следующим образом:
def func(elem):
if elem > 5:
return True
else:
return False
для чего-то вроде этого:
def func(elem):
return elem > 5
так что вы можете легко применить func(arr1)
без ошибок.
Если у вас действительно есть функция, которая возвращает просто True
или False
, я уверен, что вы сможете это сделать, независимо от ее сложности. В любом случае, мы здесь, чтобы помочь вам!
Комментарии:
1. Хотя теперь, когда я пытаюсь это сделать, кажется, что это так же медленно, как просто перебирать массив и применять func. Интересно, существуют ли другие методы / ресурсы для эффективного применения функции к каждому элементу массива.
2. Эй, какой из фрагментов кода сработал для вас? Первый с
list comprehension
или последний сnp.where
? Просто чтобы знать вашу цель…3. За np.vectorize следует понимание списка. Ну, все это «сработало», это просто вопрос скорости.
4. Я отредактировал ответ. Я думаю, что лучший способ решить вашу проблему — это работать непосредственно в вашей функции. Дайте мне знать, если это сработает. Если нет, возможно, лучше удалить этот ответ как принятый, чтобы кто-то другой мог предложить лучшее решение.
Ответ №2:
Кажется, что вы пытаетесь получить arr1
нужные вам элементы, используя func
функцию, но, судя по определению func
, работает для одного элемента. Для этого вам нужен массив True / False той же формы, arr1
что и для этого.
Если я правильно понял, потенциальным решением было бы изменить func
, чтобы работать со всем массивом, а не только с одним элементом, и возвращать массив True / False arr1.shape
нужной вам формы np.where
, поскольку вы хотите сделать это в одной строке таким образом.