2013-02-09 31 views
10

में ग्रुपिंग/क्लस्टरिंग नंबर मैंने गुगल किया है, मैंने परीक्षण किया है, और यह मेरे विट्स एंड पर है। मेरे पास संख्याओं की एक सूची है जो मुझे समानता से समूह करने की आवश्यकता है। उदाहरण के लिए, [1, 6, 9, 100, 102, 105, 109, 134, 13 9] की सूची में, 1 6 9 को एक सूची में रखा जाएगा, 100, 102, 105, और 109 को एक में रखा जाएगा सूची, और 134 और 13 9. मैं गणित में भयानक हूं, और मैंने कोशिश की है और कोशिश की है, लेकिन मैं इसे काम नहीं कर सकता। यथासंभव स्पष्ट होने के लिए, मैं उन संख्याओं को समूहित करना चाहता हूं जो एक दूसरे से 10 मूल्यों के भीतर हैं। क्या कोई मदद कर सकता है? धन्यवाद।पाइथन

+4

आपको "समानता" को और अधिक सटीक परिभाषित करने की आवश्यकता होगी। क्या आपका मतलब है, वही सैकड़ों और दस अंकों हैं? –

+0

मेरा मतलब है, अंक जो एक दूसरे के 10 (या हालांकि कई) मूल्यों के भीतर हैं। क्षमा करें, इसे यथासंभव स्पष्ट रूप से रखने की कोशिश की। –

+1

यदि संभव समूह ओवरलैप हो तो क्या होगा? – millimoose

उत्तर

21

cluster analysis करने के कई तरीके हैं। एक साधारण दृष्टिकोण लगातार डेटा तत्वों के बीच की खाई आकार को देखने के लिए है:

def cluster(data, maxgap): 
    '''Arrange data into groups where successive elements 
     differ by no more than *maxgap* 

     >>> cluster([1, 6, 9, 100, 102, 105, 109, 134, 139], maxgap=10) 
     [[1, 6, 9], [100, 102, 105, 109], [134, 139]] 

     >>> cluster([1, 6, 9, 99, 100, 102, 105, 134, 139, 141], maxgap=10) 
     [[1, 6, 9], [99, 100, 102, 105], [134, 139, 141]] 

    ''' 
    data.sort() 
    groups = [[data[0]]] 
    for x in data[1:]: 
     if abs(x - groups[-1][-1]) <= maxgap: 
      groups[-1].append(x) 
     else: 
      groups.append([x]) 
    return groups 

if __name__ == '__main__': 
    import doctest 
    print(doctest.testmod()) 
+0

और मेरा समाधान है। बहुत बहुत धन्यवाद। मैं इस कोड के हर चरित्र का अध्ययन करूंगा, हाहा। –

3

इस समूह मिलेगा:

nums = [1, 6, 9, 100, 102, 105, 109, 134, 139] 
for k, g in itertools.groupby(nums, key=lambda n: n//10): 
    print k, list(g) 

0 [1, 6, 9] 
10 [100, 102, 105, 109] 
13 [134, 139] 

ध्यान दें कि यदि nums वास्तव में अपने नमूना से पता चलता है के रूप में पृथक नहीं किया जा रहा है, पहले आपको इसे सुलझाने के लिए की आवश्यकता होगी।

+5

एकमात्र चीज जो मुझे इस दृष्टिकोण के बारे में पसंद नहीं है वह यह है कि '' [1, 6, 9, 99, 100, 134, 13 9] '' * * * * * 100 * को विभिन्न समूहों में समूहित करेगा। यह निर्धारित करने के लिए कि एक क्लस्टर शुरू होता है और दूसरा सिरों को निर्धारित करने के लिए लगातार डेटा बिंदुओं के बीच मतभेदों की गणना करना बेहतर होगा। –

+1

हाँ दुर्भाग्यवश यह हुआ कि जब मैंने इस कोड को आजमाया; /। लगभग आदर्श। –

+1

हां, जब मैंने इसे लिखा था तो इसे अवर्गीकृत किया गया था। –

2

सबसे पहले, आप आसानी से किसी भी क्रम आसन्न वस्तुओं के जोड़े के अनुक्रम में बदल सकते हैं। बस इसे टी, इसे आगे बढ़ाएं, और unshifted और unshifted प्रतियां ज़िप।

def pairify(it): 
    it0, it1 = itertools.tee(it, 2) 
    first = next(it0) 
    return zip(itertools.chain([first, first], it0), it1) 

(यह सबसे आसान तरीका नहीं है: केवल चाल है कि आप या तो (<something>, 1) या (139, <something>) के साथ शुरू करने की जरूरत है क्योंकि इस मामले में हम तत्वों की प्रत्येक जोड़ी नहीं चाहते हैं, लेकिन प्रत्येक तत्व के लिए एक जोड़ी है इसे लिखने, लेकिन मैं इस तरह से है कि जो लोग itertools से परिचित नहीं हैं के लिए सबसे अधिक पठनीय है हो सकता है लगता है।)

>>> a = [1, 6, 9, 100, 102, 105, 109, 134, 139] 
>>> list(pairify(a)) 
[(1, 1), (1, 6), (6, 9), (9, 100), (100, 102), (102, 105), (105, 109), (109, 134), (134, 139)] 

फिर, नेड Batchelder के प्रमुख के लिए थोड़ी ज्यादा जटिल संस्करण के साथ, आप बस groupby उपयोग कर सकते हैं ।

हालांकि, मुझे लगता है कि इस मामले में यह एक स्पष्ट जनरेटर से अधिक जटिल हो जाएगा जो वही काम करता है।

def cluster(sequence, maxgap): 
    batch = [] 
    for prev, val in pairify(sequence): 
     if val - prev >= maxgap: 
      yield batch 
      batch = [] 
     else: 
      batch.append(val) 
    if batch: 
     yield batch