2015-10-09 7 views
7

के साथ 2 डी सरणी बनाने का एक शानदार तरीका numpy में मैं 2 डी एरे (आर, 2 ** आर) बनाना चाहता हूं जहां कॉलम सभी संभावित बाइनरी कॉलम हैं।सभी संभावित कॉलम

उदाहरण के लिए, यदि स्तंभों की ऊंचाई 5, कॉलम होगा

[0,0,0,0,0], [0,0,0,0,1], [0,0,0,1,0], [0,0,0,1,1], [0,0,1,0,0], ... 

मेरे समाधान

np.array(list(itertools.product([0,1],repeat = c))).T 

यह बहुत बदसूरत लगता है। क्या कोई और सुरुचिपूर्ण तरीका है?

+0

मैं इसे एक राय मुद्दे के रूप में बंद करने का लुत्फ उठा रहा हूं। लालित्य बहुत ही व्यक्तिपरक है। लेकिन आप स्पीड टेस्ट से बचाए जाते हैं। :) – hpaulj

+0

@ hpaulj पूhew! :) – eleanora

उत्तर

4

आप कुछ broadcasting यहाँ है, तो तरह उपयोग कर सकते हैं -

प्रकरण # 1 (मूल r = 5):

In [217]: r = 5 

In [218]: from itertools import product 

In [219]: %timeit np.array(list(product([0,1], repeat=5))) 
10000 loops, best of 3: 33.9 µs per loop 

In [220]: %timeit np.unpackbits(np.arange(2**r,dtype='uint8')[:,None], axis=1)[:,8-r:] 
100000 loops, best of 3: 10.6 µs per loop 

In [221]: %timeit (((np.arange(2**r)[:,None] & 2**np.arange(r)[::-1]))>0).astype(int) 
10000 loops, best of 3: 31.1 µs per loop 

प्रकरण # 2 (बड़ा r):

In [242]: r = 15 

In [243]: %timeit (((np.arange(2**r)[:,None] & 2**np.arange(r)[::-1]))>0).astype(int) 
100 loops, best of 3: 6.6 ms per loop 

In [244]: %timeit np.array(list(product([0,1], repeat=r))) 
10 loops, best of 3: 77.5 ms per loop 
+0

प्रश्न में यह नहीं है? – eleanora

+0

@eleanora ओपीएस, पूरी तरह से याद किया! – Divakar

+0

@eleanora नए जोड़े गए दृष्टिकोण देखें? – Divakar

3

इसके numpy नहीं लेकिन काफी सुरुचिपूर्ण:

r = 5 
boolcols = [[y&1<<x and 1 for x in range(r)[::-1]] for y in range(2**r)] 

मध्य भाग में से कुछ स्पष्टीकरण उपयोगी हो सकता है:

y&1<<x and 1 

यह

(y&(1<<x)) and 1 

के बराबर है नाटक एक्स की सुविधा देता है = 3 और वाई = 5 हम तब प्राप्त करते हैं:

  1. 1<<x1<<3 है जो बाइनरी नोटेशन 1000 है। एक बाइनरी को बाईं ओर 3 कदम स्थानांतरित कर दिया जाता है। पायथन में आप 0b1000 या सिर्फ 8 लिख सकते हैं। को मापने के लिए timeit इस्तेमाल करने के बाद: Read more
  2. y&(1<<x) अब 5&8 जो एक बिटवाइज़ 'और' 0101 की और 1000 जो 0
  3. अब हम (0) and 1 साथ छोड़ दिया जाता है जो 0

नोट पैदावार है है अन्य समाधानों के खिलाफ इसका प्रदर्शन, यह वह नहीं है जिसे आप उपयोग करने के लिए चुनना चाहिए! मैंने जो भी परीक्षण किए हैं, उनमें धीमा है। उदाहरण के लिए:

In [21]: r = 15 

In [23]: %timeit [[y&1<<x and 1 for x in range(r)[::-1]] for y in range(2**r)] 
10 loops, best of 3: 39.8 ms per loop 

In [30]: %timeit (((np.arange(2**r)[:,None] & 2**np.arange(r)[::-1]))>0).astype(int) 
1000 loops, best of 3: 1.31 ms per loop 
+0

'np.unpackbits' समाधान केवल 8 से कम या उसके बराबर के साथ काम करता है, इसलिए शायद r> 8 के लिए बेंचमार्किंग के लिए अन्य समाधानों को आज़माएं। – Divakar

+0

परीक्षण अद्यतन (हालांकि इसी तरह के परिणाम)। – UlfR

+0

ठीक है, अभी भी इस समाधान को बुरा नहीं है :) उन बीटीडब्ल्यू के समय के लिए धन्यवाद! – Divakar

3

एक और गैर numpy समाधान:

r = 3 
print [map(int, list('{:0{w}b}'.format(x, w=r))) for x in xrange(2**r)] 

देता है:

[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]] 
+0

'टाइमिट [नक्शा (int, list ('{: 0 {w} b}' प्रारूप (x, w = r)) x में xrange (2 ** आर)] के लिए] 1 लूप, 3 में से सर्वश्रेष्ठ : 207 एमएस प्रति लूप – eleanora

1

क्या इस बारे में

np.array([list("0"*(r-1-int(np.log2(i)))+"{0:b}".format(i)) if i>0 else [i]*r for i in range(0,2**r)]).astype(int) 

संपादित

मैंने देखा है कि यह एक स्वरूपण समाधान में log2 गणना उपयोग करने के लिए अनावश्यक है:

frmt = "{0:0"+str(r)+"b}" 
print [map(int,list(frmt.format(i))) for i in range(0,2**r)] 

और समय अंतर ..np.unpackbits

(((np.arange(2**r)[:,None] & 2**np.arange(r)[::-1]))>0).astype(int) 

0 और 8 के बीच r के लिए, आप भी उपयोग कर सकते हैं - -

np.unpackbits(np.arange(2**r,dtype='uint8')[:,None], axis=1)[:,8-r:] 

रनटाइम परीक्षण

In [17]: timeit [map(int,list(frmt.format(i))) for i in range(0,2**r)] 
10000 loops, best of 3: 171 µs per loop 

In [18]: timeit np.array([list("0"*(r-1-int(np.log2(i)))+"{0:b}".format(i)) if i>0 else [i]*r for i in range(0,2**r)]).astype(int) 
1000 loops, best of 3: 514 µs per loop 
+1

'टाइमिट एनपी.एरे ([सूची (" 0 "* (आर -1-इंट (एनपी.एलएल 2 (i)) +" {0: बी} "प्रारूप (i)) अगर मैं > 0 अन्य [i] * रेंज में मैं (0,2 ** आर)])। Astype (int) ' 1 loops, 3: 332 एमएस प्रति लूप – eleanora

+0

' टाइमिट [मानचित्र (int, list (frmt.format (i))) मैं रेंज में (0,2 ** आर)] '10 लूप, 3: 17 9 एमएस प्रति लूप – eleanora

1

itertools.product एक तेजी से सी कोड है, np.array धीमी सामान्य उद्देश्य कोड है। np.fromiter, सही परिस्थितियों में, तेजी से हो सकता है। लेकिन fromiter में एक फ्लैट इनपुट की आवश्यकता है, नस्टेड सूचियों की सूची। लेकिन एक और itertools फ़्लैटिंग सूचियों का अच्छा काम करता है।

In [72]: timeit list(product([0,1],repeat=5)) 
100000 loops, best of 3: 7.03 us per loop 

In [73]: timeit list(chain(*product([0,1],repeat=5))) 
100000 loops, best of 3: 18.3 us per loop 

In [74]: timeit np.fromiter(chain(*product([0,1],repeat=5)),int,count=160).reshape(-1,5) 
10000 loops, best of 3: 33.8 us per loop 

In [75]: timeit np.array(list(product([0,1],repeat=5))) 
10000 loops, best of 3: 65.1 us per loop 

इस मामले में एक count जीत fromiter ज्यादा फर्क नहीं पड़ता है जिनमें शामिल हैं:

यहाँ कुछ iteresting समय की तुलना कर रहे हैं।

जेनरेटर चेनिंग में एक निश्चित पायथनिक लालित्य है।


तुलना की वैसे, शुद्ध numpy विधि के लिए अपने समय थोड़ा धीमा है:

In [85]: timeit (((np.arange(2**5)[:,None] & 2**np.arange(5)[::-1]))>0).astype(int) 
10000 loops, best of 3: 38.1 us per loop 

लेकिन @Divakar इस समाधान काफी बेहतर मापता है पता चलता है।

+0

आर = 15 के लिए मुझे टाइमिट सूची मिलती है (श्रृंखला (* उत्पाद ([0,1], दोहराना = आर)) 100 लूप, 3: 12.9 एमएस प्रति लूप टाइमिट सूची (श्रृंखला (* उत्पाद ([0, 1], दोहराना = आर))) 100 लूप, 3: 12.8 एमएस प्रति लूपटाइम एनपी.एरे (सूची (उत्पाद ([0,1], दोहराना = 15)) 10 लूप, सर्वोत्तम 3: 44.1 एमएस प्रति लूप मुझे आरआई = 15. – eleanora

+0

'टाइमिट ((एनपी.एरेंज (2 ** आर) [:, कोई नहीं] और 2 ** एनपी.एरेंज (आर) [:: - 1]))> 0) .astype (int) ' 100 लूप, 3 में से 3: 2.55 एमएस प्रति लूप यह बहुत तेज़ लगता है! – eleanora

संबंधित मुद्दे