2016-03-19 2 views
2

Я создаю функцию, которую я хотел бы создать случайный массив 20x20, состоящий из значений 0, 1 и 2. Я бы хотел повторить итерацию по массиву и держите подсчет количества каждого числа в массиве. Вот мой код:Как подсчитать, сколько раз значение имеет значение в массиве

%matplotlib inline 
import matplotlib.pyplot as plt 
import numpy as np 
import random 

def my_array(): 

    rand_array = np.random.randint(0,3,(20,20)) 

    zeros = 0 
    ones = 0 
    twos = 0 

    for element in rand_array: 
    if element == 0: 
     zeros += 1 
    elif element == 1: 
     ones += 1 
    else: 
     twos += 1 

    return rand_array,zeros,ones,twos 


print(my_array()) 

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

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

+0

Из любопытства, это нужно явно перебирать массив, например, домашнее задание, или вы в порядке с Python, заботясь о петлях под капотом? – Reti43

ответ

4

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

Вы можете решить проблему с помощью другого цикла for над значениями 1-мерного массива, но в коде numpy, используя for, петли очень часто представляют собой плохую идею. Обычно вы хотите использовать векторные операции и операции, транслируемые по всему массиву.

В вашем примере, вы могли бы сделать:

rand_array = np.random.randint(0,3,(20,20)) 

# no loop needed 
zeros = np.sum(rand_array == 0) 
ones = np.sum(rand_array == 1) 
twos = np.sum(rand_array == 2) 

Оператор == транслируется через весь массив, создающий булево массив. Затем sum добавляет значения True (True равно 1 в Python), чтобы получить счет.

+0

Если кому-то не требуется явная итерация по массиву, ** это ** - способ сделать это; простой, простой, понятный и эффективный. – Reti43

0

для итерации цикла по строкам, так что вы должны вставить еще один цикл для каждой строки:

%matplotlib inline 
import matplotlib.pyplot as plt 
import numpy as np 
import random 

def my_array(): 

    rand_array = np.random.randint(0,3,(20,20)) 


    zeros = 0 
    ones = 0 
    twos = 0 

    for element in rand_array: 
     for el in element: 
      if el == 0: 
       zeros += 1 
      elif el == 1: 
       ones += 1 
      else: 
       twos += 1 

    return rand_array,zeros,ones,twos 




    return rand_array 



print(my_array()) 
2

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

итерация по всем элементам

Если вы хотите перебрать каждый элемент я предложил бы использовать np.nditer. Таким образом, вы получаете доступ к каждому элементу независимо от того, сколько измерений имеет ваш массив. Вам просто нужно изменить эту строку:

for element in np.nditer(rand_array): 
# instead of "for element in rand_array:" 

Альтернативы с использованием гистограммы

Но я думаю, что есть еще лучше подход: Если у вас есть массив, содержащий дискретные значения (как целое), вы можете использовать np.histogram чтобы получить ваши счета.

Вам нужно настроить бункера, так что каждое целое число будет иметь свои собственный ящик:

bins = np.arange(np.min(rand_array)-0.5, np.max(rand_array)+1.5) 
# in your case this will give an array containing [-0.5, 0.5, 1.5, 2.5] 

Таким образом, гистограмма будет заполнить первый бункер с каждым значением между -0.5 и 0.5 (так каждый 0 вашего массива), второй бит со всеми значениями между 0.5 и 1.5 (каждый 1) и так далее.Затем вы вызываете функцию гистограммы, чтобы получить отсчеты:

counts, _ = np.histogram(rand_array, bins=bins) 
print(counts) # [130 145 125] # So 130 zeros, 145 ones, 125 twos 

Этот подход имеет то преимущество, что вам не нужно жёстко свои ценности (потому что они будут рассчитываться в пределах bins).


Как указано в комментариях, вам не нужно устанавливать бункеры как float. Вы можете использовать простые integer -bins:

bins = np.arange(np.min(rand_array), np.max(rand_array)+2) 
# [0 1 2 3] 
counts, _ = np.histogram(rand_array, bins=bins) 
print(counts) # [130 145 125] 
+1

Большое использование функции гистограммы. Использование диапазона float несколько избыточно, учитывая, что вход является массивом int, но я думаю, что он более гибкий. – Dunes

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