यह SO के आस-पास के कुछ प्रश्नों के समान है, लेकिन मैं जो चाहता हूं उसे प्राप्त करने की चाल को समझ नहीं पा रहा हूं।

मेरे पास दो सरणियाँ हैं,
गिरफ्तार आकार का (x, y, z)
आकार (x, y) के अनुक्रमणिका जो z के लिए रुचि के सूचकांक रखते हैं।

प्रत्येक अनुक्रमणिका के लिए मैं गिरफ्तारी में वास्तविक मान प्राप्त करना चाहता हूं जहां:

arr.x == indexes.x  
arr.y == indexes.y  
arr.z == indexes[x,y]

यह अनुक्रमणिका के समान आकार (x, y) की एक सरणी देगा।

उदाहरण के लिए:

arr = np.arange(99)
arr = arr.reshape(3,3,11)
indexes = np.asarray([
[0,2,2],
[1,2,3],
[3,2,10]])
# indexes.shape == (3,3)

# Example for the first element to be computed
first_element = arr[0,0,indexes[0,0]]

उपरोक्त indexes के साथ, अपेक्षित सरणियाँ इस तरह दिखाई देंगी:

expected_result = np.asarray([
[0,13,24],
[34,46,58],
[69,79,98]])

मैंने कोशिश की elements = np.take(arr, indexes, axis=z) लेकिन यह आकार की एक सरणी देता है (x, y, x, y)
मैंने elements = arr[indexes, indexes,:] जैसी चीजों को भी आजमाया लेकिन मुझे वह नहीं मिला जो मैं चाहता हूं।
मैंने कुछ उत्तर देखे जिनमें अनुक्रमित ट्रांसपोज़िंग और इसे टुपल्स में बदलना शामिल है लेकिन मुझे समझ में नहीं आता कि यह कैसे मदद करेगा।

नोट: मैं numpy के लिए थोड़ा नया हूं इसलिए मैं अभी तक पूरी तरह से अनुक्रमण को समझ नहीं पाया हूं।
आप इस सुन्न शैली को कैसे हल करेंगे?

1
Abel 1 सितंबर 2021, 16:43

3 जवाब

सबसे बढ़िया उत्तर

यह np.take_along_axis का इस्तेमाल करके किया जा सकता है

import numpy as np

#sample data
np.random.seed(0)
arr = np.arange(3*4*2).reshape(3, 4, 2) # 3d array
idx = np.random.randint(0, 2, (3, 4))   # array of indices

out = np.squeeze(np.take_along_axis(arr, idx[..., np.newaxis], axis=-1))

इस कोड में, सूचकांकों की सरणी को एक और अक्ष जोड़ा जाता है, इसलिए इसे उस सरणी arr के आकार में प्रसारित किया जा सकता है जिससे हम चयन कर रहे हैं। फिर, चूंकि np.take_along_axis के रिटर्न वैल्यू का आकार इंडेक्स की सरणी के समान है, इसलिए हमें np.squeeze का उपयोग करके इस अतिरिक्त आयाम को हटाने की आवश्यकता है।

दूसरा विकल्प np.choose का इस्तेमाल करना है, लेकिन इस मामले में, जिस अक्ष के साथ आप चयन कर रहे हैं उसे सरणी की पहली धुरी के रूप में स्थानांतरित किया जाना चाहिए:

out = np.choose(idx, np.moveaxis(arr, -1, 0))
1
bb1 1 सितंबर 2021, 17:44

यहां समाधान आपके लिए काम करेगा: 3d numpy array को 2d array के साथ इंडेक्स करना

आपके कोड के अनुकूल:

ax_0 = np.arange(arr.shape[0])[:,None]
ax_1 = np.arange(arr.shape[1])[None,:]

new_array = arr[ax_0, ax_1, indexes]
1
mdgrogan 1 सितंबर 2021, 17:20

आप np.take_along_axis के साथ ऐसा ऑपरेशन कर सकते हैं , ऑपरेशन केवल एक आयाम के साथ लागू किया जा सकता है, इसलिए आपको अपने इनपुट और सूचकांकों को फिर से आकार देना होगा।

आप जिस ऑपरेशन को करना चाहते हैं वह है:

out[i, j] = arr[i, j, indices[i, j]]

हालांकि, हमें arr और सूचकांक, यानी मैप (i, j) को k, ताकि हम np.take_along_axis लागू कर सकें। निम्नलिखित ऑपरेशन होगा:

out[k] = arr[k, indices[k]] # indexing along axis=1

यहां वास्तविक उपयोग नीचे आता है:

>>> put = np.take_along_axis(arr.reshape(9, 11), indices.reshape(9, 1), axis=1)
array([[ 0],
       [13],
       [24],
       [34],
       [46],
       [58],
       [69],
       [79],
       [91]])

फिर indices के आकार में वापस आकार दें:

>>> put.reshape(indices.shape)
array([[ 0, 13, 24],
       [34, 46, 58],
       [69, 79, 91]])
1
Ivan 1 सितंबर 2021, 17:31