2010-02-16 9 views
13

में डेटा कैसे प्राप्त करें मैं हिस्टोग्राम बिन में निहित डेटा की एक सूची प्राप्त करना चाहता हूं। मैं numpy, और Matplotlib का उपयोग कर रहा हूँ। मुझे पता है कि डेटा को कैसे पार किया जाए और बिन किनारों की जांच कैसे करें। हालांकि, मैं इसे 2 डी हिस्टोग्राम के लिए करना चाहता हूं और ऐसा करने के लिए कोड बदसूरत है। क्या यह आसान बनाने के लिए numpy कोई संरचना है?हिस्टोग्राम बिन

1 डी मामले के लिए, मैं searchsorted() का उपयोग कर सकता हूं। लेकिन तर्क इतना बेहतर नहीं है, और जब मैं नहीं चाहता हूं तो मैं वास्तव में प्रत्येक डेटा बिंदु पर बाइनरी खोज नहीं करना चाहता हूं।

अधिकांश ग़लत तर्क बिन सीमा क्षेत्रों के कारण है। सभी क्षेत्रों में इस तरह की सीमाएं हैं: [बाएं किनारे, दाएं किनारे)। अंतिम बिन को छोड़कर, जिसमें इस तरह का क्षेत्र है: [बाएं किनारे, दाएं किनारे]।

import numpy as np 

xdata = [0, 1.5, 1.5, 2.5, 2.5, 2.5, \ 
     0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, \ 
     0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 3] 
ydata = [0, 5,5, 5, 5, 5, \ 
     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \ 
     25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30] 

xbins = 3 
ybins = 3 
hist2d, xedges, yedges = np.histogram2d(xdata, ydata, bins=(xbins, ybins)) 

print 'data2d =', zip(xdata, ydata) 
print 'hist2d =' 
print hist2d 
print 'xedges =', xedges 
print 'yedges =', yedges 

getbin2d = 5 #0 through 8 

print 'find data in bin #', getbin2d 

xedge_i = getbin2d % xbins 
yedge_i = int(getbin2d/xbins) #IMPORTANT: this is xbins 

for x, y in zip(xdata, ydata): 
    # x and y left edges 
    if x >= xedges[xedge_i] and y >= yedges[yedge_i]: 
     #x right edge 
     if xedge_i == xbins-1 or x < xedges[xedge_i + 1]: 
      #y right edge 
      if yedge_i == ybins-1 or y < yedges[yedge_i + 1]: 
       print 'found:', x, y 
      #end if 
     #end if 
    #end if 
#end for 

वहाँ एक क्लीनर/अधिक कुशल यह करने के लिए रास्ता नहीं है:

import numpy as np 

data = [0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3] 

hist, edges = np.histogram(data, bins=3) 

print 'data =', data 
print 'histogram =', hist 
print 'edges =', edges 

getbin = 2 #0, 1, or 2 

print '---' 
print 'alg 1:' 

#for i in range(len(data)): 
for d in data: 
    if d >= edges[getbin]: 
     if (getbin == len(edges)-2) or d < edges[getbin+1]: 
      print 'found:', d 
     #end if 
    #end if 
#end for 

print '---' 
print 'alg 2:' 

for d in data: 
    val = np.searchsorted(edges, d, side='right')-1 
    if val == getbin or val == len(edges)-1: 
     print 'found:', d 
    #end if 
#end for 

यहाँ 2D मामले के लिए कुछ नमूना कोड है:

यहाँ -1 डी मामले के लिए कुछ नमूना कोड है? ऐसा लगता है जैसे numpy के लिए कुछ होगा।

+3

बस जिज्ञासा से बाहर; यदि आप अपने कोड में #end जैसी टिप्पणियों का उपयोग क्यों करते हैं? "हर पिक्सेल मायने रखता है" ऐसा करके आप इंडेंटेशन के उद्देश्य को अनदेखा कर रहे हैं। –

+3

2 कारण। मैं पहले एक सी ++ डेवलपर हूं, और एक पायथन डेवलपर दूसरा है। पाइथन की ब्रेसिज़ की कमी मुझे कोई अंत नहीं करती है। जब मेरे पास कई अलग-अलग इंडेंटेशन के साथ जटिल कोड ब्लॉक होते हैं, तो मैं व्हाइटस्पेस की गणना नहीं करना चाहता हूं। और मैं Emacs में अपने अधिकांश विकास करते हैं। कोड ब्लॉक पर टिप्पणियां बंद करके, यह मुझे प्रत्येक पंक्ति पर टैब दबाता है और Emacs गलत तरीके से इंडेंट करने का प्रयास नहीं करेंगे। – Ben

उत्तर

21

digitize, कोर NumPy से, आप सूचकांक बिन जो करने के लिए अपने हिस्टोग्राम में प्रत्येक मान अंतर्गत आता है की दे देंगे:

import numpy as NP 
A = NP.random.randint(0, 10, 100) 

bins = NP.array([0., 20., 40., 60., 80., 100.]) 

# d is an index array holding the bin id for each point in A 
d = NP.digitize(A, bins)  
+0

यह लगभग सही है! यदि यहां कोई numpy devs हैं, तो यह फ़ंक्शन वास्तव में हिस्टोग्राम दस्तावेज़ों के "इसे भी देखें" भाग में जाना चाहिए। यह बहुत बुरा है कि डिजिटाइज() बिन तर्क वास्तव में हिस्टोग्राम() बिन तर्क से मेल नहीं खाता है। तो इससे उपरोक्त मेरे बाकी उदाहरणों के रूप में अजीब कोड की ओर जाता है। – Ben

+1

यह बिल्कुल 'bins.searchsorted (ए,' दाएं ')' जैसा नहीं है? –

4

कैसे की तरह कुछ के बारे में: कोड का एक सा बढ़त मामलों को संभालने के लिए साथ

In [1]: data = numpy.array([0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3]) 
In [2]: hist, edges = numpy.histogram(data, bins=3) 
In [3]: for l, r in zip(edges[:-1], edges[1:]): 
    print(data[(data > l) & (data < r)]) 
    ....:  
    ....:  
[ 0.5] 
[ 1.5 1.5 1.5] 
[ 2.5 2.5 2.5] 
In [4]: 

0

pyplot.hist matplotlib में एक हिस्टोग्राम बनाता है (लेकिन यह स्क्रीन पर भी खींचता है, जिसे आप नहीं चाहते हैं)। केवल डिब्बे के लिए, आप numpy.histogram का उपयोग कर सकते हैं, जैसा कि किसी अन्य उत्तर में उल्लिखित है।

Here एक उदाहरण है जो pyploy.hist और numpy.histogram की तुलना करता है।