2010-01-27 12 views
11

बिन संख्यात्मक मानों को एक निश्चित सीमा में एक अच्छा तरीका क्या है? उदाहरण के लिए, मान लें कि मेरे पास मूल्यों की एक सूची है और मैं उन्हें अपनी सीमा से एन डिब्बे में बिन करना चाहता हूं। अभी, मैं ऐसा कुछ करता हूं:डिब्बे को अंक

from scipy import * 
num_bins = 3 # number of bins to use 
values = # some array of integers... 
min_val = min(values) - 1 
max_val = max(values) + 1 
my_bins = linspace(min_val, max_val, num_bins) 
# assign point to my bins 
for v in values: 
    best_bin = min_index(abs(my_bins - v)) 

जहां min_index न्यूनतम मान की अनुक्रमणिका देता है। विचार यह है कि आप बिन को यह देखकर देख सकते हैं कि किस बिन में इसका सबसे छोटा अंतर है।

लेकिन मुझे लगता है कि इसमें अजीब किनारे के मामले हैं। क्या मैं देख रहा हूँ डिब्बे का एक अच्छा प्रतिनिधित्व, जो कि आधे आधे खुले (ताकि वहाँ दो डिब्बे के लिए एक बिंदु बताए का कोई रास्ता नहीं है) बंद हो जाती हैं, है आदर्श यानी

bin1 = [x1, x2) 
bin2 = [x2, x3) 
bin3 = [x3, x4) 
etc... 

क्या करने के लिए एक अच्छा तरीका है पायथन में यह numpy/scipy का उपयोग कर करते हैं? मैं केवल पूर्णांक मूल्यों को बिनिंग के साथ चिंतित हूं।

आपकी मदद के लिए बहुत बहुत धन्यवाद।

+0

एक साइड नोट के रूप में: यदि यह कार्यक्षमता है तो मैं scipy/numpy के अलावा matplotlib का उपयोग करने के इच्छुक हूं। मुझे लगता है कि 'हिस्ट' जैसे कार्यों को ऐसा कुछ करना चाहिए, सिवाय इसके कि मैं किसी भी साजिश की तलाश नहीं कर रहा हूं। – user248237dfsf

उत्तर

21

numpy.histogram() वही करता है जो आप चाहते हैं।

समारोह हस्ताक्षर है:

numpy.histogram(a, bins=10, range=None, normed=False, weights=None, new=None) 

हम ज्यादातर a और bins में रुचि रखते हैं। a वह इनपुट डेटा है जिसे पिन करने की आवश्यकता है। bins कई डिब्बे हो सकते हैं (आपका num_bins), या यह स्केलर्स का अनुक्रम हो सकता है, जो बिन किनारों (आधे खुले) को दर्शाता है।

सभी लेकिन पिछले (दाएं-सबसे) बिन आधा खुला है:

import numpy 
values = numpy.arange(10, dtype=int) 
bins = numpy.arange(-1, 11) 
freq, bins = numpy.histogram(values, bins) 
# freq is now [0 1 1 1 1 1 1 1 1 1 1] 
# bins is unchanged 

documentation के शब्दों में। दूसरे शब्दों में, अगर bins है:

[1, 2, 3, 4] 

तो पहले बिन [1, 2) (1 सहित, लेकिन 2 को छोड़कर) और दूसरा [2, 3) है। पिछले बिन, तथापि,, [3, 4] है जो 4.

शामिल संपादित: आप प्रत्येक तत्व की अपनी डिब्बे में सूचकांक जानना चाहते हैं। इसके लिए, आप numpy.digitize() का उपयोग कर सकते हैं। यदि आपके डिब्बे अभिन्न होने जा रहे हैं, तो आप numpy.bincount() का भी उपयोग कर सकते हैं।

>>> values = numpy.random.randint(0, 20, 10) 
>>> values 
array([17, 14, 9, 7, 6, 9, 19, 4, 2, 19]) 
>>> bins = numpy.linspace(-1, 21, 23) 
>>> bins 
array([ -1., 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 
     10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 
     21.]) 
>>> pos = numpy.digitize(values, bins) 
>>> pos 
array([19, 16, 11, 9, 8, 11, 21, 6, 4, 21]) 

के बाद से अंतराल ऊपरी सीमा पर खुला है, सूचकांक सही हैं:

>>> (bins[pos-1] == values).all() 
True 
>>> import sys 
>>> for n in range(len(values)): 
...  sys.stdout.write("%g <= %g < %g\n" 
...    %(bins[pos[n]-1], values[n], bins[pos[n]])) 
17 <= 17 < 18 
14 <= 14 < 15 
9 <= 9 < 10 
7 <= 7 < 8 
6 <= 6 < 7 
9 <= 9 < 10 
19 <= 19 < 20 
4 <= 4 < 5 
2 <= 2 < 3 
19 <= 19 < 20 
+1

आपके उत्तर के लिए धन्यवाद - लेकिन मुझे लगता है कि हिस्टोग्राम अभी भी जो चाहता है उससे अलग है। मुझे किसी भी डिब्बे की आवृत्ति में दिलचस्पी नहीं है, मैं सिर्फ यह जानना चाहता हूं कि प्रत्येक बिंदु किस बिन में आता है। ऐसा लगता है जैसे हिस्टोग्राम उस जानकारी को वापस नहीं करता है, है ना? – user248237dfsf

+7

ओह, तो आपको 'numpy.digitize()' देखना चाहिए। –

1

इस प्रसारण का उपयोग कर numpy में काफी सरल है - नीचे मेरी उदाहरण कोड की चार पंक्तियों (गिनती नहीं है पहले दो लाइनों डिब्बे और डेटा बिंदुओं को बनाने के लिए है, जो निश्चित रूप से आमतौर पर आपूर्ति की जाएगी।)

import numpy as NP 
# just creating 5 bins at random, each bin expressed as (x, y, z) although, this code 
# is not limited by bin number or bin dimension 
bins = NP.random.random_integers(10, 99, 15).reshape(5, 3) 
# creating 30 random data points 
data = NP.random.random_integers(10, 99, 90).reshape(30, 3) 
# for each data point i want the nearest bin, but before i can generate a distance 
# matrix, i need to 'conform' the array dimensions 
# 'broadcasting' is an excellent and concise way to do this 
bins = bins[:, NP.newaxis, :] 
data2 = data[NP.newaxis, :, :] 
# now i can calculate the distance matrix 
dist_matrix = NP.sqrt(NP.sum((data - bins)**2, axis=-1)) 
bin_assignments = NP.argmin(dist_matrix, axis=0) 

'bin_assignments' से पूर्णांक मूल्यों के शामिल सूचकांकों की एक 1d सरणी है 0 से 4, पांच डिब्बे के अनुरूप - उपरोक्त 'डेटा' मैट्रिक्स में 30 मूल बिंदुओं में से प्रत्येक के लिए बिन असाइनमेंट।

+0

मैं इस उत्तर को बहुत अच्छी तरह समझ नहीं पा रहा हूं क्या आप इसे बेहतर समझा सकते हैं? –