Применить np.where против фильтрации квадратных скобок для фильтрации numpy

Я мог бы выполнять фильтрацию массивов numpy через

a[np.where(a[:,0]==some_expression)]

или

a[a[:,0]==some_expression]

Каковы (не)преимущества каждой из этих версий, особенно в отношении производительности?

С моей точки зрения, основное преимущество np.where заключается в том, что он также может давать вам результаты, когда выражение ложно. Это основной способ, которым я его использую. Вы также можете проверить, как это влияет на производительность, особенно на время выполнения.

Lior T 22.01.2019 14:59

@LiorT - не уверен, что я следую вашему комментарию, вы имеете в виду, что a[:,0]==some_expression - это ложь? a[a[:,0]==some_expression] тоже работает в этом случае

Mr_and_Mrs_D 22.01.2019 15:50

@Mr_and_Mrs_D np.where похож на функцию excel if. вы можете попросить его дать вам один ответ для мест, где какое-то условие верно, и другое значение, если это не так. например, np.where(x==10,10,0) вернет массив из 10, а нули зависят от того, равен ли x 10 или нет. это может быть полезно иногда

Lior T 22.01.2019 16:03

О, я понимаю - но в этом вопросе это не должно иметь значения

Mr_and_Mrs_D 22.01.2019 16:06
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
4
501
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

К моему удивлению, первый работает немного лучше:

a = np.random.random_integers(100, size=(1000,1))

import timeit

repeat = 3
numbers = 1000

def time(statement, _setup=None):
  print(min(
    timeit.Timer(statement, setup=_setup or setup).repeat(repeat, numbers)))

setup = """from __main__ import np, a"""

time('a[np.where(a[:,0]==99)]')
time('a[(a[:,0]==99)]')

печатает (например):

0.017856399000000023
0.019185326999999974

Увеличение размера массива приводит к тому, что числа различаются еще больше.

Булева индексация внутри преобразуется в целочисленную. Это указано в документах:

In general if an index includes a Boolean array, the result will be identical to inserting obj.nonzero() into the same position and using the integer array indexing mechanism described above.

Таким образом, сложность двух подходов одинакова. Но np.where более эффективен для больших массивов:

np.random.seed(0)
a = np.random.randint(0, 10, (10**7, 1))
%timeit a[np.where(a[:, 0] == 5)]  # 50.1 ms per loop
%timeit a[a[:, 0] == 5]            # 62.6 ms per loop

Теперь у np.where есть и другие преимущества: расширенное целочисленное индексирование хорошо работает в нескольких измерениях. Пример, когда логическое индексирование в этом аспекте не интуитивно понятно, см. в Индексация NumPy: трансляция с булевыми массивами. Поскольку np.where более эффективен, чем логическое индексирование, это просто дополнительная причина, по которой его следует предпочесть.

Но в документации np.where() говорится: «Если указано только условие, верните condition.nonzero()». Почему это не то же самое, что индексация по умолчанию с помощью логического значения, поскольку оба используют bool_array.nonzero()?

Dusch 22.01.2019 16:17

@Dusch, не уверен, я не смотрел исходный код. Скорее всего детали реализации. Мое основное мнение заключается в том, что np.where быстрее и универсальнее, поэтому, если важна эффективность, стоит многословия.

jpp 22.01.2019 16:23

Другие вопросы по теме