2010-10-27 6 views
16

में numpy/scipy में सरणी में अद्वितीय तत्वों को गिनने का कुशल तरीका मेरे पास एक scipy array है, उदा।पाइथन

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

मैं सरणी में प्रत्येक अद्वितीय तत्व की घटनाओं की संख्या की गणना करना चाहते। उदाहरण के लिए, उपर्युक्त सरणी के लिए, मैं यह जानना चाहता हूं कि [0, 0, 1], [1, 1, 1] की 2 घटनाएं और 1 [0, 0, 1] की 1 घटनाएं होती हैं।

from collections import defaultdict 
d = defaultdict(int) 

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

वहाँ एक बेहतर/अधिक कुशल तरीका है:

एक तरह से मैं इसे है कर रही के बारे में सोचा?

धन्यवाद।

+0

आपके उदाहरण कोड में Numpy/Scipy का उपयोग कहां है? या क्या यह केवल इस विचार को समझने के लिए है, इसे हल करने के लिए एक Numpy/Scipy फ़ंक्शन होना चाहते हैं? – Zelphir

उत्तर

8

अगर पायथन 2.7 (या 3.1) के साथ चिपके हुए कोई मुद्दा नहीं है और इन दो अजगर संस्करणों के किसी भी शायद नई collections.Counter आप के लिए कुछ करता है, तो आप tuples जैसे तत्वों 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})

हालांकि, मैंने इन दो दृष्टिकोणों पर कोई प्रदर्शन परीक्षण नहीं किया है।

+5

डिफ़ॉल्ट डिक्शनरी तेज होगी। जॉन माचिन ने इसे आज के जवाब में समय के साथ दिखाया (http://stackoverflow.com/questions/4036474/add-new-keys-to-a-dictionary-while-incrementing-existing-values)। –

+0

जानना अच्छा है :-) धन्यवाद :-) –

+1

ओपी के शीर्षक द्वारा अनुरोध किए गए अनुसार, Numpy/Scipy का उपयोग नहीं करता है। पायथन के पुराने संस्करणों के उपयोग की भी वकालत करता है। सुनिश्चित नहीं है कि यह एक अच्छा जवाब है। – Zelphir

1
अजगर के लिए

2,6 <

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))}) 
4

आप पंक्तियों से सरणी कोषगत और अंक जहां पंक्तियों को बदलने के लिए रंग-रूप सॉर्ट कर सकते हैं:

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]) 

शब्दकोश का भी इस्तेमाल किया जा सकता है। कौन सी विभिन्न विधियां सबसे तेज़ी से होंगी, उन सरणीओं पर निर्भर करती हैं जिनके साथ आप वास्तव में काम कर रहे हैं।

0

numpy_indexed पैकेज (अस्वीकरण: मैं इसका लेखक हूं) चक द्वारा पोस्ट किए गए एक जैसा समाधान प्रदान करता है; जो एक अच्छी तरह से वेक्टरकृत है। लेकिन परीक्षणों के साथ, एक अच्छा इंटरफेस, और कई और संबंधित उपयोगी कार्य:

import numpy_indexed as npi 
npi.count(a)