NumPy

2011-08-24 20 views
8
में बूलियन सूचकांक मुखौटा के कई स्तरों का उपयोग

मैं निम्नलिखित कोड है जो पहले एक तार्किक सूचकांक मुखौटा के साथ एक NumPy सरणी के तत्वों का चयन करता है:NumPy

import numpy as np 

grid = np.random.rand(4,4) 
mask = grid > 0.5 

मैं करने के लिए यह एक के खिलाफ एक दूसरे बूलियन मुखौटा उपयोग करना चाहते हैं

masklength = len(grid[mask]) 
prob = 0.5 
# generates an random array of bools 
second_mask = np.random.rand(masklength) < prob 

# this fails to act on original object 
grid[mask][second_mask] = 100 

यह काफी एक ही समस्या यह तो सवाल के रूप में सूचीबद्ध नहीं है: के साथ वस्तुओं बाहर लेने Numpy array, how to select indices satisfying multiple conditions? - के रूप में मैं यादृच्छिक संख्या पीढ़ी का उपयोग कर रहा, मैं चाहता हूँ एक पूर्ण मुखौटा उत्पन्न करने के लिए, केवल चयनित तत्वों के लिए पहला मुखौटा

उत्तर

6

मेरा मानना ​​है कि निम्नलिखित है कि तुम क्या कह रहे हैं करता है:

grid[[a[second_mask] for a in np.where(mask)]] = 100 

यह इस प्रकार के रूप में काम करता है:

  • np.where(mask) सूचकांक जहां mask यह सच है में बूलियन मुखौटा धर्मान्तरित;
  • [a[second_mask] for a in ...] इंडेक्स को केवल उन लोगों का चयन करने के लिए सबसेट करता है जहां second_mask सत्य है।

आपका मूल संस्करण काम नहीं करने का कारण यह है कि grid[mask] में फैंसी इंडेक्सिंग शामिल है। यह डेटा की एक प्रति बनाता है, जिसके परिणामस्वरूप ...[second_mask] = 100 मूल सरणी की बजाय उस प्रति को संशोधित करता है।

+0

बिल्कुल सही, जो मैं खोज रहा था। – Hemmer

+0

क्या आपके द्वारा पोस्ट किए गए स्निपेट में शामिल सरणी की कोई प्रतिलिपि भी है? – Hemmer

+1

@ हेमर: 'np.where' और 'a [second_mask]' द्वारा बनाए गए नए सरणी हैं। उन सरणी का आकार 'मास्क' और 'second_mask' में ट्रू तत्वों की संख्या पर निर्भर करता है और 'ग्रिड' के आकार से स्वतंत्र होता है। – NPE

0

एक और संभावित समाधान जो मैं इसके बारे में सोचने के बाद आया था, दूसरा नक्शा पहले के आकार को बनाए रखना है (जो मेमोरी हिट के लायक नहीं हो सकता है) और चुनिंदा नए तत्वों में जोड़ें :

#!/usr/bin/env python 
import numpy as np 

prob = 0.5  
grid = np.random.rand(4,4) 

mask = grid > 0.5 
masklength = np.sum(mask) 

# initialise with false map 
second_mask = np.zeros((4,4), dtype=np.bool) 
# then selectively add to this map using the second criteria 
second_mask[mask] = np.random.rand(masklength) < prob 

# this now acts on the original object 
grid[second_mask] = 100 

हालांकि इस थोड़ा अधिक समय है, यह बेहतर (मेरी शुरुआत आँखों के लिए), और गति परीक्षण में यह एक ही समय में प्रदर्शन को पढ़ने के लिए लगता है।

grid.flat[np.flatnonzero(mask)[second_mask]] = 100 

यह विश्लेषण करना:

ind = np.flatnonzero(mask) 

सूचकांक के एक फ्लैट सरणी जहां mask सच है, जो तब second_mask लगाने से आगे का भी नाश कर रहा है उत्पन्न करता है

2

फ्लैट अनुक्रमण का प्रयोग सिरदर्द के बहुत से बचा जाता है :

ind = ind[second_mask] 

हम आगे बढ़ सकते हैं:

ind = ind[third_mask] 

अंत में

grid.flat[ind] = 100 

ind साथ अनुक्रमित grid के एक फ्लैट संस्करण और 100 प्रदान करती है। grid.ravel()[ind] = 100 भी काम करेगा, क्योंकि ravel() मूल सरणी में एक फ्लैट दृश्य देता है।

0
In [29]: ar = linspace(1,10,10) 
In [30]: ar[(3<ar)*(ar<8)] 
Out[30]: array([ 4., 5., 6., 7.])