Эффективный способ подсчета уникальных элементов в массиве в numpy / scipy в Python - PullRequest
16 голосов
/ 28 октября 2010

У меня есть массив scipy, например,

a = array([[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]])

Я хочу посчитать количество вхождений каждого уникального элемента в массиве. Например, для вышеуказанного массива a я хочу получить, что есть 1 вхождение [0, 0, 1], 2 вхождения [1, 1, 1] и 1 вхождение [1, 0, 1].

Один из способов, которым я думал об этом:

from collections import defaultdict
d = defaultdict(int)

for elt in a:
  d[elt] += 1

есть ли лучший / более эффективный способ?

спасибо.

Ответы [ 4 ]

8 голосов
/ 28 октября 2010

Если придерживаться Python 2.7 (или 3.1) не является проблемой, и вам доступна любая из этих двух версий Python, возможно, новая collection.Counter может вам пригодиться, если вы придерживаетесь hashableтакие элементы, как кортежи:

>>> from collections import Counter
>>> c = Counter([(0,0,1), (1,1,1), (1,1,1), (1,0,1)])
>>> c
Counter({(1, 1, 1): 2, (0, 0, 1): 1, (1, 0, 1): 1})

Я не проводил никаких тестов производительности на этих двух подходах.

4 голосов
/ 30 октября 2010

Вы можете отсортировать массив лексикографически по строкам и искать точки, где строки изменяются:

In [1]: a = array([[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]])

In [2]: b = a[lexsort(a.T)]

In [3]: b
Out[3]: 
array([[0, 0, 1],
       [1, 0, 1],
       [1, 1, 1],
       [1, 1, 1]])

...


In [5]: (b[1:] - b[:-1]).any(-1)
Out[5]: array([ True,  True, False], dtype=bool)

Последний массив говорит, что первые три строки отличаются, а третья строка повторяется дважды.

Для массивов единиц и нулей вы можете закодировать значения:

In [6]: bincount(dot(a, array([4,2,1])))
Out[6]: array([0, 1, 0, 0, 0, 1, 0, 2])

Также можно использовать словари. Какой из различных методов будет наиболее быстрым, зависит от типа массивов, с которыми вы на самом деле работаете.

1 голос
/ 28 октября 2010

для Python 2.6 <</p>

import itertools

data_array = [[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]]

dict_ = {}

for list_, count in itertools.groupby(data_array):
    dict_.update({tuple(list_), len(list(count))})
0 голосов
/ 02 апреля 2016

Пакет numpy_indexed (заявление об отказе от ответственности: я его автор) предоставляет решение, аналогичное тому, которое опубликовал chuck; который хорошо векторизован. Но с тестами, приятным интерфейсом и многими другими полезными функциями:

import numpy_indexed as npi
npi.count(a)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...