Numpy जहां कई स्थितियां कार्य करती हैं


132

मेरे पास दूरी की एक सरणी है जिसे डिस्ट्स कहा जाता है। मैं ऐसे डिस्ट्रेस का चयन करना चाहता हूं जो दो मूल्यों के बीच हों। मैंने ऐसा करने के लिए कोड की निम्नलिखित पंक्ति लिखी है:

 dists[(np.where(dists >= r)) and (np.where(dists <= r + dr))]

हालांकि यह केवल शर्त के लिए चयन करता है

 (np.where(dists <= r + dr))

अगर मैं एक अस्थायी चर का उपयोग करके क्रमिक रूप से कमांड करता हूं तो यह ठीक काम करता है। उपरोक्त कोड काम क्यों नहीं करता है, और मुझे यह कैसे काम करना है?

चियर्स

जवाबों:


203

आपके विशेष मामले में सबसे अच्छा तरीका यह होगा कि आप अपने दो मानदंडों को एक मानदंड में बदल दें:

dists[abs(dists - r - dr/2.) <= dr/2.]

यह केवल एक बूलियन सरणी बनाता है, और मेरी राय में इसे पढ़ना आसान है क्योंकि यह कहता है, है distएक के भीतर drया r? (यदि मैं rशुरुआत के बजाय आपके हित के क्षेत्र के केंद्र को फिर से परिभाषित करूंगा , तो r = r + dr/2.) लेकिन यह आपके प्रश्न का उत्तर नहीं देता है।


आपके प्रश्न का उत्तर:
आपको वास्तव में ज़रूरत नहीं है whereयदि आप सिर्फ उन तत्वों को छानने की कोशिश कर रहे हैं जो distsआपके मानदंड में फिट नहीं हैं:

dists[(dists >= r) & (dists <= r+dr)]

क्योंकि &वसीयत आपको एक तत्वबोध देगी and(कोष्ठक आवश्यक हैं)।

या, यदि आप उपयोग करना चाहते हैं where किसी कारण कर सकते हैं:

 dists[(np.where((dists >= r) & (dists <= r + dr)))]

क्यों:
कारण यह काम नहीं करता है क्योंकि np.whereसूचकांकों की एक सूची देता है, न कि एक बूलियन सरणी। आप andसंख्याओं की दो सूचियों के बीच पाने की कोशिश कर रहे हैं , जो निश्चित रूप से आपके द्वारा अपेक्षित True/ Falseमान नहीं है । यदि aऔर bदोनों Trueमान हैं, तो a and bवापस लौटता है b। तो ऐसा कुछ कहना [0,1,2] and [2,3,4]बस आपको देगा [2,3,4]। यहाँ यह कार्रवाई में है:

In [230]: dists = np.arange(0,10,.5)
In [231]: r = 5
In [232]: dr = 1

In [233]: np.where(dists >= r)
Out[233]: (array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),)

In [234]: np.where(dists <= r+dr)
Out[234]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)

In [235]: np.where(dists >= r) and np.where(dists <= r+dr)
Out[235]: (array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]),)

आप जिस चीज की तुलना करने की उम्मीद कर रहे थे, वह उदाहरण के तौर पर बूलियन ऐरे थी

In [236]: dists >= r
Out[236]: 
array([False, False, False, False, False, False, False, False, False,
       False,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True], dtype=bool)

In [237]: dists <= r + dr
Out[237]: 
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True, False, False, False, False, False,
       False, False], dtype=bool)

In [238]: (dists >= r) & (dists <= r + dr)
Out[238]: 
array([False, False, False, False, False, False, False, False, False,
       False,  True,  True,  True, False, False, False, False, False,
       False, False], dtype=bool)

अब आप np.whereसंयुक्त बूलियन सरणी पर कॉल कर सकते हैं :

In [239]: np.where((dists >= r) & (dists <= r + dr))
Out[239]: (array([10, 11, 12]),)

In [240]: dists[np.where((dists >= r) & (dists <= r + dr))]
Out[240]: array([ 5. ,  5.5,  6. ])

या बस फैंसी इंडेक्सिंग का उपयोग करके बूलियन सरणी के साथ मूल सरणी को अनुक्रमित करें

In [241]: dists[(dists >= r) & (dists <= r + dr)]
Out[241]: array([ 5. ,  5.5,  6. ])

61

स्वीकृत उत्तर ने समस्या को अच्छी तरह समझाया। हालांकि, कई शर्तों को लागू करने के लिए अधिक Numpythonic दृष्टिकोण संख्यात्मक तार्किक कार्यों का उपयोग करना है । इस ase में आप उपयोग कर सकते हैं np.logical_and:

np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr)))

11

यहाँ इंगित करने के लिए एक दिलचस्प बात; OR और AND का उपयोग करने का सामान्य तरीका इस मामले में काम करेगा, लेकिन एक छोटे से बदलाव के साथ। "और" के बजाय और "या" के बजाय, Ampersand (&) और पाइप ऑपरेटर () का उपयोग करें। और यह काम करेगा।

जब हम 'और' का उपयोग करते हैं :

ar = np.array([3,4,5,14,2,4,3,7])
np.where((ar>3) and (ar<6), 'yo', ar)

Output:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

जब हम Ampersand (&) का उपयोग करते हैं :

ar = np.array([3,4,5,14,2,4,3,7])
np.where((ar>3) & (ar<6), 'yo', ar)

Output:
array(['3', 'yo', 'yo', '14', '2', 'yo', '3', '7'], dtype='<U11')

और यह उसी स्थिति में है जब हम पांडा डेटाफ्रेम के मामले में कई फिल्टर लगाने की कोशिश कर रहे हैं। अब इसके पीछे तर्क तार्किक ऑपरेटरों और बिटवाइज़ ऑपरेटरों के साथ कुछ करना है और उसी के बारे में अधिक समझ के लिए, मैं इस उत्तर के माध्यम से जाने का सुझाव दूंगा या स्टैकओवरफ़्लो में समान क्यू / ए के ।

अपडेट करें

एक उपयोगकर्ता ने पूछा, कोष्ठक के अंदर (ar> 3) और (ar <6) देने की आवश्यकता क्यों है। खैर यहाँ बात है। इससे पहले कि मैं यहां क्या हो रहा है, के बारे में बात करना शुरू करने से पहले, एक को पायथन में ऑपरेटर पूर्वता के बारे में जानना होगा।

BODMAS के बारे में ऐसा ही है, अजगर पहले इस बात की भी मिसाल देता है कि पहले क्या किया जाना चाहिए। कोष्ठक के अंदर की वस्तुओं को पहले किया जाता है और फिर बिटवाइज़ ऑपरेटर काम करता है। मैं नीचे दिखाऊंगा कि दोनों मामलों में क्या होता है जब आप उपयोग करते हैं और उपयोग नहीं करते हैं "(", ")"।

मामला एक:

np.where( ar>3 & ar<6, 'yo', ar)
np.where( np.array([3,4,5,14,2,4,3,7])>3 & np.array([3,4,5,14,2,4,3,7])<6, 'yo', ar)

चूंकि यहां कोई ब्रैकेट नहीं हैं, इसलिए बिटवाइज़ ऑपरेटर ( &) यहां भ्रमित हो रहा है कि आप इसे तार्किक और क्या प्राप्त करने के लिए भी कह रहे हैं, क्योंकि ऑपरेटर पूर्वता तालिका में यदि आप देखते हैं, तो ऑपरेटर या ऑपरेटरों &पर पूर्वता दी जाती है । यहां सबसे कम वरीयता से सर्वोच्च वरीयता तक की तालिका दी गई है।<>

यहाँ छवि विवरण दर्ज करें

यह ऑपरेशन और ऑपरेशन भी नहीं कर रहा है <और >तार्किक और ऑपरेशन करने के लिए कहा जा रहा है। तो इसलिए यह उस त्रुटि देता है।

ऑपरेटर निम्नलिखित के बारे में अधिक जानने के लिए निम्न लिंक को देख सकता है

अब केस टू:

यदि आप ब्रैकेट का उपयोग करते हैं, तो आप स्पष्ट रूप से देखते हैं कि क्या होता है।

np.where( (ar>3) & (ar<6), 'yo', ar)
np.where( (array([False,  True,  True,  True, False,  True, False,  True])) & (array([ True,  True,  True, False,  True,  True,  True, False])), 'yo', ar)

ट्रू और फाल्स की दो सरणियाँ। और आप आसानी से उन पर तार्किक और ऑपरेशन कर सकते हैं। जो आपको देता है:

np.where( array([False,  True,  True, False, False,  True, False, False]),  'yo', ar)

और बाकी आप जानते हैं, दिए गए मामलों के लिए, जहाँ भी सही है, पहले मूल्य (यानी यहाँ 'यो') और यदि गलत है, तो दूसरा (यानी यहाँ, मूल रखते हुए) असाइन करता है।

बस इतना ही। मुझे उम्मीद है कि मैंने क्वेरी को अच्छी तरह से समझाया।


1
आपको ()इधर (ar>3)- उधर क्यों करना पड़ता है (ar>6)?
RTrain3k

यह वास्तव में एक अच्छा सवाल है। यह इतना अच्छा सवाल है कि मुझे खुद सोचना होगा कि पृथ्वी पर इसकी क्या जरूरत है। तो मैंने किया, एक सहयोगी से भी पूछा और हमने चर्चा की कि अब आपके पास मेरे लिए एक समाधान है। उत्तर में इसे एक अद्यतन के रूप में लाना। यह वास्तव में सरल है फिर भी वास्तव में समझना एक कठिन बात है।
अमित अमोला

अपडेट RTrain3k चेकआउट करें, मैंने आपकी क्वेरी का उत्तर दिया है।
अमित अमोला

5

मुझे np.vectorizeऐसे कार्यों के लिए उपयोग करना पसंद है। निम्नलिखित को धयान मे रखते हुए:

>>> # function which returns True when constraints are satisfied.
>>> func = lambda d: d >= r and d<= (r+dr) 
>>>
>>> # Apply constraints element-wise to the dists array.
>>> result = np.vectorize(func)(dists) 
>>>
>>> result = np.where(result) # Get output.

आप np.argwhereइसके बजाय np.whereस्पष्ट आउटपुट के लिए उपयोग कर सकते हैं । लेकिन वह आपकी कॉल है :)

आशा करता हूँ की ये काम करेगा।



2

यह काम करना चाहिए:

dists[((dists >= r) & (dists <= r+dr))]

सबसे सुंदर तरीका ~~



0

मैंने इसका सरल उदाहरण दिया है

import numpy as np

ar = np.array([3,4,5,14,2,4,3,7])

print [X for X in list(ar) if (X >= 3 and X <= 6)]

>>> 
[3, 4, 5, 4, 3]

6
इस मामले में पुनरावृति की आवश्यकता नहीं है। NumPy में बूलियन इंडेक्सिंग है।
M456
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.