Какой самый эффективный способ проверить, существует ли значение в массиве NumPy? - PullRequest
47 голосов
/ 17 августа 2011

У меня очень большой массив NumPy

1 40 3
4 50 4
5 60 7
5 49 6
6 70 8
8 80 9
8 72 1
9 90 7
.... 

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

Спасибо!

Ответы [ 7 ]

56 голосов
/ 17 августа 2011

Как насчет

if value in my_array[:, col_num]:
    do_whatever

Редактировать: Я думаю, __contains__ реализован таким образом, что это то же самое, что и версия @ detly

37 голосов
/ 17 августа 2011

Самым очевидным для меня будет:

np.any(my_array[:, 0] == value)
30 голосов
/ 17 августа 2011

Чтобы проверить несколько значений, вы можете использовать numpy.in1d ​​(), который является поэлементной версией функции ключевого слова python. Если ваши данные отсортированы, вы можете использовать numpy.searchsorted ():

import numpy as np
data = np.array([1,4,5,5,6,8,8,9])
values = [2,3,4,6,7]
print np.in1d(values, data)

index = np.searchsorted(data, values)
print data[index] == values
11 голосов
/ 11 августа 2016

Захватывающий.Мне нужно было повысить скорость серии циклов, которые должны выполнять сопоставление индекса таким же образом.Поэтому я решил найти здесь все решения, а также некоторые риффы.

Вот мои тесты скорости для Python 2.7.10:

import timeit
timeit.timeit('N.any(N.in1d(sids, val))', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

18.86137104034424

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = [20010401010101+x for x in range(1000)]')

15.061666011810303

timeit.timeit('N.in1d(sids, val)', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

11.613027095794678

timeit.timeit('N.any(val == sids)', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

7.670552015304565

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

5.610057830810547

timeit.timeit('val == sids', setup = 'import numpy as N; val = 20010401020091; sids = N.array([20010401010101+x for x in range(1000)])')

1.663232291616* 0,0548710823059082

timeit.timeit('val in sids', setup = 'import numpy as N; val = 20010401020091; sids = dict(zip([20010401010101+x for x in range(1000)],[True,]*1000))')

0,054754018783569336

Очень удивительно!Разница в порядках!

Подводя итог, если вы просто хотите узнать, есть ли что-то в одномерном списке или нет:

  • 19s N.any (N.in1d ​​(массив numpy))
  • 15 с x in (список)
  • 8 с N.any (x == массив numpy)
  • 6 s x in (массив numpy)
  • .1 с x в (набор или словарь)

Если вы также хотите узнать, где что-то есть в списке (порядок важен):

  • 12s N.in1d(x, массив numpy)
  • 2s x == (массив numpy)
1 голос
/ 29 сентября 2014

Добавление ответа @ HYRY in1d кажется самым быстрым для numpy. Это использует numpy 1.8 и python 2.7.6.

В этом тесте in1d был самым быстрым:

a = arange(0,99999,3)
%timeit 10 in a
%timeit in1d(a, 10)

10000 loops, best of 3: 150 µs per loop
10000 loops, best of 3: 61.9 µs per loop

Использование набора Python кажется самым быстрым:

s = set(range(0, 99999, 3))
%timeit 10 in s

10000000 loops, best of 3: 47 ns per loop
0 голосов
/ 20 ноября 2018

Самый удобный способ, на мой взгляд, это:

(Val in X[:, col_num])

где Val - значение, которое вы хотите проверить, а X - массив. В вашем примере предположим, что вы хотите проверить, существует ли значение 8 в третьем столбце. Просто напишите

(8 in X[:, 2])

Это вернет True, если в третьем столбце есть 8, иначе False.

0 голосов
/ 08 августа 2018

Если вы хотите проверить, находится ли список a в массиве numpy b, используйте следующий синтаксис:

np.any(np.equal(a, b).all(axis=1))

Помещение axis = 1 с учетом того, что массив numpy имеет форму n*2

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