2012-02-27 12 views
16

मैं numpy जो या एक बग नहीं हो सकता में निम्नलिखित विषमता भर में आया था:नामित टाइप प्रकार: एक [0] ['नाम'] और एक ['नाम'] [0] के बीच अंतर?

import numpy as np 
dt = np.dtype([('tuple', (int, 2))]) 
a = np.zeros(3, dt) 
type(a['tuple'][0]) # ndarray 
type(a[0]['tuple']) # ndarray 

a['tuple'][0] = (1,2) # ok 
a[0]['tuple'] = (1,2) # ValueError: shape-mismatch on array construction 

मैं उम्मीद है कि काम नीचे दिए गए विकल्पों के दोनों। राय?

+1

युक्ति: एसओ को कोड पोस्ट करते समय, कृपया उन बिट्स पोस्ट करें जिन्हें हम कट-पेस्ट कर सकते हैं; पायथन के मामले में, इसका मतलब है कि डाली गई टिप्पणियों के लिए '#' का उपयोग करना, '%' नहीं। – DSM

+1

मजेदार सामान, मैं यह भी 1.6.1 का उपयोग कर एक ही परिणाम दे रहा हूं ... –

+0

थोड़ा अजीब, लेकिन 'एक [0] [' tuple '] [:] = (1,2)' काम करता है, शायद वहाँ एक सुराग है ... –

उत्तर

1

यह एक अपस्ट्रीम बग था, जो NumPy PR #5947 के रूप में तय किया गया था, जिसमें 1.9.3 में एक फिक्स था।

8

मुझे कोई दूसरी त्रुटि से आप (numpy 1.7.0.dev का प्रयोग करके) कर मिलती है:

ValueError: setting an array element with a sequence. 

तो नीचे दिए गए विवरण के अपने सिस्टम के लिए सही नहीं हो सकता है (या तो यह और भी गलत हो सकता है जो मैं देखता हूं उसके लिए स्पष्टीकरण)।

सबसे पहले, आप देखते हैं कि structured array की एक पंक्ति का अनुक्रमण आप एक numpy.void वस्तु देता है (data type docs देख)

import numpy as np 
dt = np.dtype([('tuple', (int, 2))]) 
a = np.zeros(3, dt) 
print type(a[0]) # = numpy.void 

मैं क्या समझ से, void प्रकार का अजगर सूची की तरह है, क्योंकि यह अलग की वस्तुओं धारण कर सकते हैं डेटा प्रकार, जो समझ में आता है क्योंकि संरचित सरणी में कॉलम अलग-अलग डेटा प्रकार हो सकते हैं।

, तो अनुक्रमण के बजाय, आप पहली पंक्ति बाहर काट, आप एक ndarray:

print type(a[:1]) # = numpy.ndarray 

इस के अनुरूप है कैसे अजगर सूचियों के काम:

b = [1, 2, 3] 
print b[0] # 1 
print b[:1] # [1] 

स्लाइसिंग एक छोटा संस्करण रिटर्न मूल अनुक्रम का, लेकिन अनुक्रमण एक तत्व देता है (यहां, int; ऊपर, void प्रकार)।

तो जब आप संरचित सरणी की पंक्तियों में फिसलते हैं, तो आपको इसकी अपेक्षा करना चाहिए कि यह आपकी मूल सरणी (केवल कम पंक्तियों के साथ) जैसा व्यवहार करे। अपने उदाहरण के साथ सतत, अब आप पहली पंक्ति की 'टपल' कॉलम के लिए प्रदान कर सकते हैं:

a[:1]['tuple'] = (1, 2) 

तो, ... क्यों नहीं a[0]['tuple'] = (1, 2) काम करता है?

ठीक है, याद रखें कि a[0]void ऑब्जेक्ट देता है। इसलिए, जब आप

a[0]['tuple'] = (1, 2) # this line fails 

फोन आपको लगता है कि void वस्तु की 'टपल' तत्व के लिए एक tuple बताए जा रहे हैं। नोट: इस तथ्य के बावजूद आप इस सूचकांक 'टपल' कहा जाता है, यह एक ndarray के रूप में जमा किया गया था:

print type(a[0]['tuple']) # = numpy.ndarray 

तो, यह मतलब है टपल एक ndarray में डाला जाना चाहिए। लेकिन, void ऑब्जेक्ट असाइनमेंट नहीं डाला जा सकता है (यह केवल एक अनुमान है) क्योंकि इसमें मनमाना डेटा प्रकार हो सकते हैं, इसलिए यह नहीं पता कि किस प्रकार कास्ट करना है।इस के आसपास पाने के लिए आप इनपुट अपने आप को कास्ट कर सकते हैं:

a[0]['tuple'] = np.array((1, 2)) 

तथ्य यह है कि हम विभिन्न त्रुटियों मिल पता चलता है कि इसके बाद के संस्करण लाइन पतों त्रुटि मुझे प्राप्त कास्टिंग के बाद से आप के लिए काम नहीं कर सकते --- नहीं जिसका आप प्राप्त ।

परिशिष्ट:

तो क्यों निम्नलिखित काम करता है?

a[0]['tuple'][:] = (1, 2) 

यहाँ, आप सरणी में का अनुक्रमण रहे हैं जब आप [:] जोड़ने के लिए, लेकिन यह है कि बिना, आप void वस्तु में का अनुक्रमण कर रहे हैं। दूसरे शब्दों में, a[0]['tuple'][:] कहता है "संग्रहित सरणी के तत्वों को प्रतिस्थापित करें" (जिसे सरणी द्वारा नियंत्रित किया जाता है), a[0]['tuple'] कहता है "संग्रहित सरणी को प्रतिस्थापित करें" (जिसे void द्वारा प्रबंधित किया जाता है)।

उपसंहार:

अजीब पर्याप्त, पंक्ति (0 के साथ अर्थात अनुक्रमण) तक पहुँचने आधार सरणी ड्रॉप करने लगता है, लेकिन यह अभी भी आप आधार सरणी के लिए आवंटित करने के लिए अनुमति देता है।

print a['tuple'].base is a # = True 
print a[0].base is a # = False 
a[0] = ((1, 2),) # `a` is changed 

शायद void नहीं वास्तव में एक सरणी तो यह, एक आधार सरणी नहीं है ... लेकिन फिर क्यों यह एक base विशेषता है?

+0

आपके लिए बक्षीस – bmu

9

मैंने पूछा कि numpy-चर्चा सूची पर। ट्रैविस ओलीफंत ने here का उत्तर दिया।

The short answer is that this is not really a "normal" bug, but it could be considered a "design" bug (although the issues may not be straightforward to resolve). What that means is that it may not be changed in the short term --- and you should just use the first spelling.

Structured arrays can be a confusing area of NumPy for several of reasons. You've constructed an example that touches on several of them. You have a data-type that is a "structure" array with one member ("tuple"). That member contains a 2-vector of integers.

First of all, it is important to remember that with Python, doing

a['tuple'][0] = (1,2)

is equivalent to

b = a['tuple']; b[0] = (1,2)

In like manner,

a[0]['tuple'] = (1,2)

is equivalent to

b = a[0]; b['tuple'] = (1,2)

To understand the behavior, we need to dissect both code paths and what happens. You built a (3,) array of those elements in 'a'. When you write b = a['tuple'] you should probably be getting a (3,) array of (2,)-integers, but as there is currently no formal dtype support for (n,)-integers as a general dtype in NumPy, you get back a (3,2) array of integers which is the closest thing that NumPy can give you. Setting the [0] row of this object via

a['tuple'][0] = (1,2)

works just fine and does what you would expect.

On the other hand, when you type:

b = a[0]

you are getting back an array-scalar which is a particularly interesting kind of array scalar that can hold records. This new object is formally of type numpy.void and it holds a "scalar representation" of anything that fits under the "VOID" basic dtype.

For some reason:

b['tuple'] = [1,2]

is not working. On my system I'm getting a different error: TypeError: object of type 'int' has no len()

I think this should be filed as a bug on the issue tracker which is for the time being here: http://projects.scipy.org/numpy

The problem is ultimately the void->copyswap function being called in voidtype_setfields if someone wants to investigate. I think this behavior should work.

इस के लिए एक व्याख्या a numpy bug report में दी गई है:

उसके जवाब का उल्लेख करते हुए।

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