NumPy सरणी से विशिष्ट पंक्तियों और स्तंभों का चयन करना


96

मैं यह जानने की कोशिश कर रहा हूं कि मैं यहां क्या गलत कर रहा हूं।

मैं NumPy का उपयोग कर रहा हूं, और मेरे पास विशिष्ट पंक्ति सूचकांक और विशिष्ट कॉलम सूचकांक हैं जिनसे मैं चयन करना चाहता हूं। यहाँ मेरी समस्या का सार है:

import numpy as np

a = np.arange(20).reshape((5,4))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19]])

# If I select certain rows, it works
print a[[0, 1, 3], :]
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [12, 13, 14, 15]])

# If I select certain rows and a single column, it works
print a[[0, 1, 3], 2]
# array([ 2,  6, 14])

# But if I select certain rows AND certain columns, it fails
print a[[0,1,3], [0,2]]
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# ValueError: shape mismatch: objects cannot be broadcast to a single shape

ये क्यों हो रहा है? निश्चित रूप से मुझे पहली, दूसरी और चौथी पंक्तियों और पहली और तीसरी कॉलम का चयन करने में सक्षम होना चाहिए? परिणाम मैं उम्मीद कर रहा हूँ:

a[[0,1,3], [0,2]] => [[0,  2],
                      [4,  6],
                      [12, 14]]

टैग की गईं सुधरने योग्यता को सुधारने के लिए सुन्न (इसके अलावा शब्द 'स्लाइस' और 'स्लाइसिंग'
प्लेनटेक्स्ट

जवाबों:


86

फैंसी इंडेक्सिंग के लिए आपको प्रत्येक आयाम के लिए सभी सूचकांक प्रदान करने की आवश्यकता होती है। आप पहले एक के लिए 3 सूचकांक प्रदान कर रहे हैं, और दूसरे के लिए केवल 2, इसलिए त्रुटि। आप ऐसा कुछ करना चाहते हैं:

>>> a[[[0, 0], [1, 1], [3, 3]], [[0,2], [0,2], [0, 2]]]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

यह निश्चित रूप से लिखने के लिए एक दर्द है, इसलिए आप प्रसारण को आपकी मदद करने दे सकते हैं:

>>> a[[[0], [1], [3]], [0, 2]]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

यदि आप सूचियों के साथ अनुक्रमणिका बनाते हैं, तो यह बहुत सरल है, सूचियाँ नहीं:

>>> row_idx = np.array([0, 1, 3])
>>> col_idx = np.array([0, 2])
>>> a[row_idx[:, None], col_idx]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

4
धन्यवाद, मुझे नहीं पता था कि आप ऐसा कर सकते हैं! प्रसारण अजीब और अद्भुत है ... दो साल के सुन्न के बाद, मुझे अभी भी इसकी आदत है।
प्रवीण

2
धन्यवाद! जबकि अन्य उत्तरों ने चयनित मैट्रिक्स को वापस करने के संदर्भ में मेरे प्रश्न का सही उत्तर दिया, इस उत्तर ने यह भी बताया कि असाइनमेंट के मुद्दे को संबोधित करते समय ([[0,1,3], [0,2]] = 0 सेट कैसे करें , उदाहरण के लिए)।
माइक सी।

1
@ जयम - कल ही मैंने एक-लाइनर का निर्माण किया, जो आपके द्वारा सुझाई गई ब्रॉडकास्टिंग ट्रिक को करने के लिए है: np.ix_
प्रवीण

1
क्या कोई इस बारे में स्पष्टीकरण दे सकता है कि वाक्य रचना इस तरह क्यों काम करती है? क्या कारण है कि यह पहले उदाहरण के लिए काम करता है लेकिन तीसरे के लिए नहीं। और यह भी, अपनी सूची में वांछित सूचकांकों को कैसे हल किया जाता है? धन्यवाद
Aetos

2
पंक्तियों को नेस्टेड करने की आवश्यकता क्यों है और कर्नल नहीं हैं?
अट्टुरसम्स

86

Toan पता चलता है, एक सरल हैक सिर्फ पहली पंक्तियों का चयन करें, और तब से अधिक स्तंभों का चयन करने के लिए किया जाएगा कि

>>> a[[0,1,3], :]            # Returns the rows you want
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [12, 13, 14, 15]])
>>> a[[0,1,3], :][:, [0,2]]  # Selects the columns you want as well
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

[संपादित करें] अंतर्निहित विधि: np.ix_

मुझे हाल ही में पता चला है कि numpy आपको वास्तव में @Jaime का सुझाव देने के लिए इन-बिल्ट वन-लाइनर देता है , लेकिन प्रसारण सिंटैक्स का उपयोग किए बिना (जो पठनीयता की कमी से ग्रस्त है)। डॉक्स से:

Ix_ का उपयोग करके जल्दी से इंडेक्स एरे का निर्माण किया जा सकता है जो क्रॉस उत्पाद को इंडेक्स करेगा। a[np.ix_([1,3],[2,5])]सरणी देता है [[a[1,2] a[1,5]], [a[3,2] a[3,5]]]

तो आप इसे इस तरह से उपयोग करें:

>>> a = np.arange(20).reshape((5,4))
>>> a[np.ix_([0,1,3], [0,2])]
array([[ 0,  2],
       [ 4,  6],
       [12, 14]])

और जिस तरह से यह काम करता है वह Jaime द्वारा सुझाए गए तरीके को संरेखित करने में ध्यान रखता है, ताकि प्रसारण ठीक से हो सके:

>>> np.ix_([0,1,3], [0,2])
(array([[0],
        [1],
        [3]]), array([[0, 2]]))

इसके अलावा, जैसा कि एक टिप्पणी में माइक कहता है, np.ix_को एक दृश्य वापस करने का फायदा है, जो मेरे पहले (पूर्व-संपादन) उत्तर में नहीं था। इसका मतलब है कि अब आप अनुक्रमित सरणी में असाइन कर सकते हैं :

>>> a[np.ix_([0,1,3], [0,2])] = -1
>>> a    
array([[-1,  1, -1,  3],
       [-1,  5, -1,  7],
       [ 8,  9, 10, 11],
       [-1, 13, -1, 15],
       [16, 17, 18, 19]])

4
कुछ परीक्षणों में, मैंने np.ix_पहले कॉलम और फिर पंक्तियों को चुनने की विधि से भी तेज पाया (आमतौर पर 2x के बारे में उपवास के आकार के वर्ग परीक्षण के मेरे परीक्षण 1K-10K जहां आप सभी पंक्तियों और स्तंभों को फिर से जोड़ते हैं)।
नाथन

7

उपयोग:

 >>> a[[0,1,3]][:,[0,2]]
array([[ 0,  2],
   [ 4,  6],
   [12, 14]])

या:

>>> a[[0,1,3],::2]
array([[ 0,  2],
   [ 4,  6],
   [12, 14]])

10
हालांकि यह सही है, तो आप अधिक जानकारी का एक सा समझा पोस्टिंग पर विचार करना चाहिए क्यों कि यह सही है।
ebarr

2

इसका उपयोग करना np.ix_सबसे सुविधाजनक तरीका है (जैसा कि दूसरों द्वारा उत्तर दिया गया है), लेकिन यहाँ एक और दिलचस्प तरीका है:

>>> rows = [0, 1, 3]
>>> cols = [0, 2]

>>> a[rows].T[cols].T

array([[ 0,  2],
       [ 4,  6],
       [12, 14]])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.