सुन्न का उपयोग करते हुए अजीब अनुक्रमण


27

मेरे पास एक चर, x है, जो आकार का है (2,2,50,100)।

मेरे पास एक सरणी है, y, जो np.array ([0,10,20]) के बराबर है। एक अजीब बात तब होती है जब मैं x [0,:,:, y] को इंडेक्स करता हूं।

x = np.full((2,2,50,100),np.nan)
y = np.array([0,10,20])
print(x.shape)
(2,2,50,100)
print(x[:,:,:,y].shape)
(2,2,50,3)
print(x[0,:,:,:].shape)
(2,50,100)
print(x[0,:,:,y].shape)
(3,2,50)

अंतिम एक आउटपुट (3,2,50) और (2,50,3) क्यों नहीं है?


मैं बहुत नया हूँ, इसलिए मेरे पास आपके प्रश्न का उत्तर नहीं है। इसके आगे की जांच करने के लिए, मैं एक छोटा उदाहरण खोजने का सुझाव देता हूं जो केवल 2D या 3D है और किसी भी अक्ष पर अधिकतम 10 तत्वों की तरह है।
कोड-अपरेंटिस

जवाबों:


21

यह है कि कैसे सरणी आकार प्रसारण के लिए उन्नत अनुक्रमित का उपयोग करता है। जब आप 0पहले इंडेक्स के लिए पास होते हैं , और yआखिरी इंडेक्स के लिए, खसखस ​​को 0उसी आकार में प्रसारित किया जाएगा y। निम्नलिखित समानता रखती है x[0,:,:,y] == x[(0, 0, 0),:,:,y]:। यहाँ एक उदाहरण है

import numpy as np

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

np.equal(x[0,:,:,y], x[(0, 0, 0),:,:,y]).all()
# returns:
True

अब, क्योंकि आप प्रभावी रूप से सूचकांकों के दो सेटों में गुजर रहे हैं, तो आप सूचकांकों के जोड़े (इस मामले में) बनाने के लिए उन्नत अनुक्रमण एपीआई का उपयोग कर रहे हैं।

x[(0, 0, 0),:,:,y])

# equivalent to
[
  x[0,:,:,y[0]], 
  x[0,:,:,y[1]], 
  x[0,:,:,y[2]]
]

# equivalent to
rows = np.array([0, 0, 0])
cols = y
x[rows,:,:,cols]

# equivalent to
[
  x[r,:,:,c] for r, c in zip(rows, columns)
]

जिसका पहला आयाम है, जिसकी लंबाई समान है y। यह जो आप देख रहे हैं।

एक उदाहरण के रूप में, 4 आयामों के साथ एक सरणी को देखें जो अगले भाग में वर्णित हैं:

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

# x looks like:
array([[[[  0,   1,   2,   3,   4],    -+      =+
         [  5,   6,   7,   8,   9],     Sheet1  |
         [ 10,  11,  12,  13,  14],     |       |
         [ 15,  16,  17,  18,  19]],   -+       |
                                                Workbook1
        [[ 20,  21,  22,  23,  24],    -+       |
         [ 25,  26,  27,  28,  29],     Sheet2  |
         [ 30,  31,  32,  33,  34],     |       |
         [ 35,  36,  37,  38,  39]],   -+       |
                                                |
        [[ 40,  41,  42,  43,  44],    -+       |
         [ 45,  46,  47,  48,  49],     Sheet3  |
         [ 50,  51,  52,  53,  54],     |       |
         [ 55,  56,  57,  58,  59]]],  -+      =+


       [[[ 60,  61,  62,  63,  64],
         [ 65,  66,  67,  68,  69],
         [ 70,  71,  72,  73,  74],
         [ 75,  76,  77,  78,  79]],

        [[ 80,  81,  82,  83,  84],
         [ 85,  86,  87,  88,  89],
         [ 90,  91,  92,  93,  94],
         [ 95,  96,  97,  98,  99]],

        [[100, 101, 102, 103, 104],
         [105, 106, 107, 108, 109],
         [110, 111, 112, 113, 114],
         [115, 116, 117, 118, 119]]]])

x अनुक्रमिक रूप को समझने में वास्तव में आसान है जिसे हम अब दिखाने के लिए उपयोग कर सकते हैं कि क्या हो रहा है ...

पहला आयाम 2 एक्सेल वर्कबुक होने जैसा है, दूसरा आयाम प्रत्येक वर्कबुक में 3 शीट होने जैसा है, तीसरा आयाम 4 शीट प्रति शीट की तरह है, और अंतिम आयाम प्रत्येक पंक्ति (या शीट प्रति कॉलम) के लिए 5 मान है।

इसे इस तरह से देखते हुए, पूछना x[0,:,:,0], यह कहना है: "पहली कार्यपुस्तिका में, प्रत्येक पत्रक के लिए, प्रत्येक पंक्ति के लिए, मुझे पहला मूल्य / स्तंभ दें।"

x[0,:,:,y[0]]
# returns:
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

# this is in the same as the first element in:
x[(0,0,0),:,:,y]

लेकिन अब उन्नत अनुक्रमण के साथ, हम x[(0,0,0),:,:,y]"पहली कार्यपुस्तिका में, प्रत्येक पत्रक के लिए, प्रत्येक पंक्ति के लिए, मुझे yवें मान / स्तंभ दे सकते हैं। ठीक है, अब इसे प्रत्येक मान के लिए कर सकते हैं y"।

x[(0,0,0),:,:,y]
# returns:
array([[[ 0,  5, 10, 15],
        [20, 25, 30, 35],
        [40, 45, 50, 55]],

       [[ 2,  7, 12, 17],
        [22, 27, 32, 37],
        [42, 47, 52, 57]],

       [[ 4,  9, 14, 19],
        [24, 29, 34, 39],
        [44, 49, 54, 59]]])

जहां यह पागल हो जाता है कि इंडेक्स सरणी के बाहरी आयामों से मेल करने के लिए संख्यात्मक प्रसारित होगा । इसलिए यदि आप ऊपर भी वैसा ही ऑपरेशन करना चाहते हैं, लेकिन BOTH "एक्सेल वर्कबुक" के लिए, आपको लूप और कॉन्सिलेट नहीं करना है। आप केवल पहले आयाम के लिए एक सरणी पास कर सकते हैं, लेकिन यह एक सुसंगत आकार होना चाहिए

पूर्णांक पास करने से प्रसारण हो जाता है y.shape == (3,)। यदि आप किसी सरणी को पहले सूचकांक के रूप में पास करना चाहते हैं, तो सरणी के अंतिम आयाम के साथ संगत होना चाहिए y.shape। यानी, पहले इंडेक्स का अंतिम आयाम या तो 3 या 1 होना चाहिए।

ix = np.array([[0], [1]])
x[ix,:,:,y].shape
# each row of ix is broadcast to length 3:
(2, 3, 3, 4)

ix = np.array([[0,0,0], [1,1,1]])
x[ix,:,:,y].shape
# this is identical to above:
(2, 3, 3, 4)

ix = np.array([[0], [1], [0], [1], [0]])
x[ix,:,:,y].shape
# ix is broadcast so each row of ix has 3 columns, the length of y
(5, 3, 3, 4)

डॉक्स में संक्षिप्त विवरण मिला: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing


संपादित करें:

मूल प्रश्न से, अपनी इच्छित सदस्यता का एक-लाइनर प्राप्त करने के लिए, आप इसका उपयोग कर सकते हैं x[0][:,:,y]:

x[0][:,:,y].shape
# returns
(2, 50, 3)

हालांकि, यदि आप उन उप-वर्गों को निर्दिष्ट करने का प्रयास कर रहे हैं, तो आपको बहुत सावधान रहना होगा कि आप मूल सरणी के साझा स्मृति दृश्य को देख रहे हैं। अन्यथा असाइनमेंट मूल सरणी के लिए नहीं होगा, बल्कि एक कॉपी होगा।

साझा की गई मेमोरी केवल तब होती है जब आप अपने एरे को कम करने के लिए एक पूर्णांक या स्लाइस का उपयोग करते हैं, x[:,0:3,:,:]या x[0,:,:,1:-1]

np.shares_memory(x, x[0])
# returns:
True

np.shares_memory(x, x[:,:,:,y])
# returns:
False

आपके मूल प्रश्न और मेरे उदाहरण दोनों yमें न तो कोई इंट या स्लाइस है, इसलिए हमेशा मूल की एक कॉपी को असाइन करना होगा।

परंतु! क्योंकि आपके सरणी yको एक स्लाइस के रूप में व्यक्त किया जा सकता है, आप वास्तव में अपने सरणी के माध्यम से एक देखने योग्य दृश्य प्राप्त कर सकते हैं :

x[0,:,:,0:21:10].shape
# returns:
(2, 50, 3)

np.shares_memory(x, x[0,:,:,0:21:10])
# returns:
True

# actually assigns to the original array
x[0,:,:,0:21:10] = 100

यहां हम 0:21:10प्रत्येक इंडेक्स को खींचने के लिए स्लाइस का उपयोग करते हैं जो अंदर होगा range(0,21,10)। हमें उपयोग करना है 21और नहीं 20क्योंकि स्टॉप-पॉइंट को स्लाइस से बाहर रखा गया है, जैसे rangeफ़ंक्शन में।

तो मूल रूप से, यदि आप एक स्लाइस का निर्माण कर सकते हैं जो आपके निर्बल मानदंडों को पूरा करता है, तो आप असाइनमेंट कर सकते हैं।


4

इसे कहते हैं combining advanced and basic indexing। में combining advanced and basic indexing, सुन्न पहले उन्नत अनुक्रमण में अनुक्रमण करते हैं और मूल अनुक्रमण के आयाम के परिणामस्वरूप / उप-स्थान को संक्षिप्त करते हैं।

डॉक्स से उदाहरण:

बता दें कि x.shape (10,20,30,40,50) है और मान लीजिए कि ind_1 और ind_2 को आकार (2,3,4) में प्रसारित किया जा सकता है। तब x [:, ind_1, ind_2] का आकार (10,2,3,4,40,50) है, क्योंकि X से (20,30) आकार के उप-स्थान को (2,3,4) से उप-स्थान से बदल दिया गया है सूचकांकों। हालाँकि, x [:, ind_1,:, ind_2] का आकार (2,3,4,10,30,50) है क्योंकि अनुक्रमणिका उप-स्थान में छोड़ने के लिए कोई भी अस्पष्ट स्थान नहीं है, इस प्रकार यह शुरू में ही निपट जाता है । हमेशा वांछित कहीं भी उप-चाल को स्थानांतरित करने के लिए .transpose () का उपयोग करना संभव है। ध्यान दें कि इस उदाहरण का उपयोग करके दोहराया नहीं जा सकता है।

तो, पर x[0,:,:,y], 0और yअग्रिम अनुक्रमण कर रहे हैं। वे एक साथ आयाम प्रसारित करने के लिए प्रसारित किए जाते हैं (3,)

In [239]: np.broadcast(0,y).shape
Out[239]: (3,)

यह (3,)बनाने के लिए 2 और 3 के आयाम की शुरुआत से जुड़ा हुआ है(3, 2, 50)

यह देखने के लिए कि प्रथम और अंतिम आयाम वास्तव में एक साथ प्रसारित हो रहे हैं, आप बदलाव का प्रयास कर सकते हैं 0 करने के लिए [0,1]प्रसारण की त्रुटि को देखने के लिए

print(x[[0,1],:,:,y])

Output:
IndexError                                Traceback (most recent call last)
<ipython-input-232-5d10156346f5> in <module>
----> 1 x[[0,1],:,:,y]

IndexError: shape mismatch: indexing arrays could not be broadcast together with
 shapes (2,) (3,)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.