Как посчитать значения в определенном диапазоне в массиве Numpy? - PullRequest
39 голосов
/ 05 марта 2012

У меня есть массив значений NumPy.Я хочу посчитать, сколько из этих значений в определенном диапазоне, скажем, х <100 и х> 25.Я читал о счетчике, но, похоже, он действителен только для указанных значений, а не диапазонов значений.Я искал, но не нашел ничего относительно моей конкретной проблемы.Если бы кто-то мог указать мне на надлежащую документацию, я был бы признателен.Спасибо

Я пробовал это

   X = array(X)
   for X in range(25, 100):
       print(X)

Но он просто дает мне цифры от 25 до 99.

РЕДАКТИРОВАТЬ Данные яЯ использую была создана другой программой.Затем я использовал скрипт для чтения данных и сохранения их в виде списка.Затем я взял список и превратил его в массив, используя array (r).

Редактировать

Результат выполнения

 >>> a[0:10]
 array(['29.63827346', '40.61488812', '25.48300065', '26.22910525',
   '42.41172923', '20.15013315', '34.95323355', '13.03604098',
   '29.71097606', '9.53222141'], 
  dtype='<U11')

Ответы [ 5 ]

71 голосов
/ 05 марта 2012

Если ваш массив называется a, число элементов, удовлетворяющих 25 < x < 100, равно

((25 < a) & (a < 100)).sum()

Выражение (25 < a) & (a < 100) приводит к логическому массиву такой же формы, что и a сзначение True для всех элементов, которые удовлетворяют условию.Суммирование по этому логическому массиву обрабатывает True значения как 1 и False значения как 0.

9 голосов
/ 05 марта 2012

Вы можете использовать histogram.Вот базовый пример использования:

>>> import numpy
>>> a = numpy.random.random(size=100) * 100 
>>> numpy.histogram(a, bins=(0.0, 7.3, 22.4, 55.5, 77, 79, 98, 100))
(array([ 8, 14, 34, 31,  0, 12,  1]), 
 array([   0. ,    7.3,   22.4,   55.5,   77. ,   79. ,   98. ,  100. ]))

В вашем конкретном случае это будет выглядеть примерно так:

>>> numpy.histogram(a, bins=(25, 100))
(array([73]), array([ 25, 100]))

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

>>> strings = [str(i) for i in range(10)]
>>> numpy.array(strings)
array(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], 
      dtype='|S1')
>>> numpy.array(strings, dtype=float)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
8 голосов
/ 07 мая 2012

Опираясь на хороший подход Свена, вы также можете сделать более прямой:

numpy.count_nonzero((25 < a) & (a < 100))

Сначала создается массив логических значений с одним логическим значением для каждого входного числа в массиве a, а затем подсчитывается количество не ложных (т. Е. Истинных) значений (что дает число совпадающих чисел).

Обратите внимание, однако, что этот подход в два раза медленнее, чем подход .sum() Свена, для массива чисел 100k (NumPy 1.6.1, Python 2.7.3) - около 300 мкс против 150 мкс.

4 голосов
/ 05 марта 2012

Ответ Свена - способ сделать это, если вы не хотите дополнительно обрабатывать совпадающие значения.
Следующие два примера возвращают копии только с совпадающими значениями:

np.compress((25 < a) & (a < 100), a).size

Или:

a[(25 < a) & (a < 100)].size

Пример сеанса интерпретатора:

>>> import numpy as np
>>> a = np.random.randint(200,size=100)
>>> a
array([194, 131,  10, 100, 199, 123,  36,  14,  52, 195, 114, 181, 138,
       144,  70, 185, 127,  52,  41, 126, 159,  39,  68, 118, 124, 119,
        45, 161,  66,  29, 179, 194, 145, 163, 190, 150, 186,  25,  61,
       187,   0,  69,  87,  20, 192,  18, 147,  53,  40, 113, 193, 178,
       104, 170, 133,  69,  61,  48,  84, 121,  13,  49,  11,  29, 136,
       141,  64,  22, 111, 162, 107,  33, 130,  11,  22, 167, 157,  99,
        59,  12,  70, 154,  44,  45, 110, 180, 116,  56, 136,  54, 139,
        26,  77, 128,  55, 143, 133, 137,   3,  83])
>>> np.compress((25 < a) & (a < 100),a).size
34
>>> a[(25 < a) & (a < 100)].size
34

В вышеприведенных примерах используются "побитовое и" (&) для поэлементного вычисления двух логических массивов, которые вы создаете для сравнения. Например, можно написать отличный ответ Свена:

np.bitwise_and(25 < a, a < 100).sum() 

Булевы массивы содержат значения True, когда условие соответствует, и False, если оно не выполняется.
Бонусный аспект логических значений заключается в том, что True эквивалентно 1, а False - 0.

2 голосов
/ 05 марта 2012

Я думаю, что ответ @Sven Marnach довольно приятный, потому что он работает на самом массиве numpy, который будет быстрым и эффективным (реализация C).

Мне нравится помещать тест в одно условие, например 25 < x < 100, поэтому я бы, вероятно, сделал это примерно так:

len([x for x in a.ravel() if 25 < x < 100])

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