numpy

2012-03-31 16 views
27

में मैट्रिक्स के विकर्ण के मानों को बदलना, मैं मैटिक्स के विकर्ण के मानों को numpy में कैसे बदल सकता हूं?numpy

मैंने Numpy modify ndarray diagonal की जांच की, लेकिन वहां पर कार्य numpy v 1.3.0 में लागू नहीं किया गया है।

कहते हैं कि हम एक np.array एक्स है और मैं 0.

+1

आप किस प्रकार का उपयोग कर रहे हैं? 'np.diag_indices_from' को v1.4 – JoshAdel

+0

याप में जोड़ा गया था, आप सही हैं, मैं वर्तमान में पाइथन बनाम 1.3.0 – pacodelumberg

+0

@ लैंगरहंस द्वीपों का उपयोग कर रहा हूं उम्मीद है कि आपका मतलब शून्य 1.3 है, पायथन 1.3 नहीं (जो कि नब्बे के दशक के मध्य में आया था .. ।: पी) – Dougal

उत्तर

36

क्या आपने numpy.fill_diagonal को आजमाया था? निम्नलिखित answer और यह discussion देखें। या दस्तावेज से निम्नलिखित (हालांकि वर्तमान में टूट):

http://docs.scipy.org/doc/numpy/reference/generated/numpy.fill_diagonal.html

+0

धन्यवाद @JoshAdel – Mellkor

+0

+1 यह numpy में ऐसा करने का सही तरीका है। निर्मित लूप के लिए दो का उपयोग करते हुए एक समय में सरणी एक तत्व को पुन: स्थापित करने के लिए हमेशा बेहतर होता है। – JoshAdel

2
def replaceDiagonal(matrix, replacementList): 
    for i in range(len(replacementList)): 
     matrix[i][i] = replacementList[i] 

कहाँ आकार एक n x, n मैट्रिक्स में n है करने के लिए विकर्ण के सभी मूल्यों को निर्धारित करना चाहते हैं।

+3

या 'एन = लेन (replace_list); मैट्रिक्स [: एन,: एन] = replace_list'। यह पाइथन में बजाय सी में लूप करता है और इसलिए बहुत तेज़ होगा। – Dougal

+0

@Dougal: बहुत बढ़िया, मुझे यह नहीं पता था। क्या आप इसे उत्तर के रूप में पोस्ट कर सकते हैं? –

+0

निश्चित रूप से, [बस किया] [http://stackoverflow.com/a/9959707/344821)। – Dougal

12

आपको लगता है कि fill_diagonal या diag_indices_from (right way एक निरंतर करने के लिए विकर्ण स्थापित करने के लिए) नहीं है numpy के एक संस्करण का उपयोग कर रहे हैं, आप सरणी टुकड़ा करने की क्रिया के साथ बहुत आसानी से कर सकते हैं:

# assuming a 2d square array 
n = mat.shape[0] 
mat[range(n), range(n)] = 0 

यह अजगर में स्पष्ट पाश की तुलना में बहुत तेजी से होता है, क्योंकि पाशन सी में होता है और संभवतः vectorized है।

इस बारे में एक अच्छी बात यह है कि आप लगातार मूल्य (जैसे diagflat) के बजाय तत्वों की सूची के साथ एक विकर्ण भी भर सकते हैं, लेकिन एक नया बनाने के बजाय मौजूदा मैट्रिक्स को संशोधित करने के लिए)। उदाहरण के लिए, इस 0, 1, 2 करने के लिए अपने मैट्रिक्स की विकर्ण सेट हो जाएगा ...:

# again assuming 2d square array 
n = mat.shape[0] 
mat[range(n), range(n)] = range(n) 

आप अधिक सरणी आकार समर्थन करने की आवश्यकता है, तो यह अधिक जटिल है (जिसके कारण fill_diagonal अच्छा है। ..):

m[list(zip(*map(range, m.shape)))] = 0 

(list कॉल अजगर 3, जहां zip पुनरावर्तक रिटर्न में केवल आवश्यक है)

+0

भविष्य के पाठकों के लिए इसे स्पष्ट करने के लिए, 'mat [: n,: n] = 0' केवल सरणी/matrix_ से 0 को सेट करता है, केवल विकर्ण तत्व नहीं। 'ज़िप 'संस्करण वास्तव में डायग करता है। – gorlum0

+0

@ gorlum0 Whoops - इसे इंगित करने के लिए धन्यवाद। मैंने इसे ठीक करने के लिए अभी संपादित किया है ('ज़िप' वास्तव में वहां आवश्यक नहीं है) '। – Dougal

+0

कूल, यहां तक ​​कि नंगे 'श्रेणी'। यह अंतर्निहित सामान जानना मुश्किल है। – gorlum0

9

यहाँ यह करने के लिए एक और अच्छा तरीका है।।

A.ravel()[:A.shape[1]**2:A.shape[1]+1] 

i'th superdiagonal उपयोग के लिए:

A.ravel()[i:max(0,A.shape[1]-i)*A.shape[1]:A.shape[1]+1] 

i'th subdiagonal उपयोग के लिए:

A.ravel()[A.shape[1]*i:A.shape[1]*(i+A.shape[1]):A.shape[1]+1] 
आप सरणी के मुख्य विकर्ण उपयोग की एक आयामी दृश्य चाहते हैं

या सामान्य रूप से, मेरे विकर्ण के लिए जहां मुख्य विकर्ण 0 है, उपधाराएं नकारात्मक हैं और सुपरडायोनल सकारात्मक हैं, उपयोग करें:

A.ravel()[max(i,-A.shape[1]*i):max(0,(A.shape[1]-i))*A.shape[1]:A.shape[1]+1] 

ये विचारों और नहीं प्रतियां हैं, इसलिए वे तेजी से एक विकर्ण निकालने के लिए चलाया जाएगा, लेकिन नई सरणी वस्तु में किए गए बदलाव मूल सरणी पर लागू होंगे। मेरी मशीन पर इन्हें मुख्य विकर्ण को स्थिर करते समय fill_diagonal फ़ंक्शन से तेज़ी से चलाया जाता है, लेकिन यह हमेशा मामला नहीं हो सकता है। इन्हें केवल एक स्थिर के बजाय विकर्ण में मानों की सरणी असाइन करने के लिए भी उपयोग किया जा सकता है।

नोट्स: छोटे सरणी के लिए यह flat NumPy सरणी का गुण उपयोग करने के लिए तेज़ हो सकता है। यदि गति एक प्रमुख मुद्दा है तो यह A.shape[1] एक स्थानीय चर बनाने के लिए लायक हो सकता है। इसके अलावा, यदि सरणी संगत नहीं है, ravel() एक प्रतिलिपि वापस कर देगा, इसलिए, एक स्ट्रैड स्लाइस को मान असाइन करने के लिए, स्ट्रक्ड स्लाइस उत्पन्न करने के लिए उपयोग की जाने वाली मूल सरणी को रचनात्मक रूप से टुकड़ा करना आवश्यक होगा (यदि यह संगत है) या flat विशेषता का उपयोग करने के लिए।

इसके अलावा, मूल रूप से यह योजना बनाई गई थी कि NumPy 1.10 में और बाद में सरणी की 'विकर्ण' विधि प्रतिलिपि के बजाय एक दृश्य वापस कर देगी। हालांकि यह परिवर्तन अभी तक नहीं बनाया गया है, लेकिन उम्मीद है कि किसी बिंदु पर इस चाल को देखने के लिए अब आवश्यक नहीं होगा। http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.diagonal.html

+0

अच्छा और हैकी, मुझे यह पसंद है! केवल चेतावनी है कि मुझे लगता है कि आपको 'wrap = True' व्यवहार [' np.fill_diagonal' दस्तावेज़] में वर्णित होगा (http://docs.scipy.org/doc/numpy/reference/generated/numpy.fill_diagonal.html)। आप शायद हल कर सकते हैं कि आपके स्लाइस में पर्याप्त स्टॉप वैल्यू जोड़ना। – Jaime

+0

धन्यवाद, अच्छा पकड़ो। मैंने बस इसे और कुछ अन्य चीजों को ठीक करने के लिए संपादित किया। – IanH

1
>>> a = numpy.random.rand(2,2) 
>>> a 
array([[ 0.41668355, 0.07982691], 
     [ 0.60790982, 0.0314224 ]]) 
>>> a - numpy.diag(numpy.diag(a)) 
array([[ 0.  , 0.07982691], 
     [ 0.60790982, 0.  ]]) 
4

मिनिमल देखें। कोड।

X[np.diag_indices_from(X)] = 0. 

screenshot

1

आप निम्न कर सकते।

मान लें कि आपका मैट्रिक्स 4 * 4 मैट्रिक्स है।

indices_diagonal = np.diag_indices(4) 

yourarray[indices_diagonal] = Val