2012-03-05 3 views
26

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

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

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

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

EDIT данные я использую был создан другой программой. Затем я использовал скрипт для чтения данных и сохранил его как список. Затем я взял список и включил его в массив с использованием массива (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') 
+0

@ Senderle, что это ему большое спасибо !! Я попробовал метод Свена после преобразования массива, и он отлично работал! Еще раз спасибо – Surfcast23

ответ

48

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

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

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

+1

@SvenI попробовал ваш метод, но получил эту ошибку '' TypeError: unorderable types: int() Surfcast23

+1

@ Surfcast23: [Работает для меня.] (Https: //gist.github. com/1975690) Какую версию NumPy и Python вы используете? –

+0

Я запускаю Python 3.2 – Surfcast23

6

Вы можете использовать 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])) 

Кроме того, если у вас есть список строк, вы должны явно указать тип, поэтому знает, как создать массив поплавков вместо списка строк.

>>> 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.]) 
+0

Я дам ему попробовать спасибо! – Surfcast23

+0

@ Surfcast23, да, этот более универсальный, но если вам действительно нужен только один бит, [Sven] (http://stackoverflow.com/a/9560228/577088) будет быстрее. – senderle

+0

Я запустил код и получил '' (array ([- 481], dtype = int32), array ([25, 100])) '' Что касается меня, это отрицательный знак, как его интерпретировать? – Surfcast23

3

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

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.

+0

@Sevn и Адам, я все еще довольно новое для питона ~ 6 месяцев не очень стабильно, хотя. Можете ли вы, ребята, объяснить, как и почему работают ваши скрипты? Спасибо – Surfcast23

+0

Или укажите мне, где я могу это прочитать. – Surfcast23

+0

@ Surfcast23: Я добавил немного объяснений. Держись! Не сдавайся! – bernie

2

Я думаю @Sven Marnach ответ очень хорошо, потому что он работает в на самом Numpy массив, который будет быстрым и эффективным (C).

Я хотел поставить тест на одно условие, как 25 < x < 100, так что я бы, наверное, сделать это что-то вроде этого:

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

+1

Nice. Использовать gen-expr: 'sum (1 для i в a.ravel(), если 25 bernie

+0

, что тоже хорошо. сначала я пытался использовать 'len()' на генераторе, и, к моему удивлению, он не работает. – wim

+0

@wim: 'len()' не работает с выражениями генератора, потому что итераторы обычно не имеют конечной длины. Вот почему подход 'sum (1 ...)' лучше: он имеет фиксированный и намного меньший объем памяти, поскольку вам не нужно создавать промежуточный список. – EOL

5

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

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

Это первый создает массив логических значений с одним булевыми для каждого входного числа в массиве a, а затем подсчитать количество не ЛОЖЬ (т.е. True) значений (что дает Numbe r совпадающих чисел).

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

Смежные вопросы