पता लगाएँ कि क्या एक NumPy सरणी में कम से कम एक गैर-संख्यात्मक मान है?


103

मुझे एक फ़ंक्शन लिखने की ज़रूरत है जो यह पता लगाएगी कि इनपुट में कम से कम एक मूल्य है जो गैर-संख्यात्मक है। यदि एक गैर-संख्यात्मक मान पाया जाता है, तो मैं एक त्रुटि बढ़ाऊंगा (क्योंकि गणना को केवल एक संख्यात्मक मान वापस करना चाहिए)। इनपुट सरणी के आयामों की संख्या अग्रिम में ज्ञात नहीं है - फ़ंक्शन को ndim की परवाह किए बिना सही मूल्य देना चाहिए। एक अतिरिक्त जटिलता के रूप में इनपुट एक एकल फ्लोट या numpy.float64शून्य-विषम सरणी की तरह कुछ विषम हो सकता है ।

इसे हल करने का स्पष्ट तरीका एक पुनरावर्ती कार्य लिखना है जो कि सरणी में प्रत्येक चलने योग्य वस्तु पर पुनरावृत्ति करता है जब तक कि यह एक गैर-पुनरावृत्ति नहीं पाता। यह numpy.isnan()प्रत्येक गैर-चलने योग्य ऑब्जेक्ट पर फ़ंक्शन को लागू करेगा । यदि कम से कम एक गैर-संख्यात्मक मूल्य पाया जाता है, तो फ़ंक्शन तुरंत गलत वापस आ जाएगा। अन्यथा यदि चलने योग्य सभी मान संख्यात्मक हैं, तो यह अंतत: सत्य हो जाएगा।

यह ठीक काम करता है, लेकिन यह बहुत धीमा है और मुझे उम्मीद है कि NumPy के पास इसे करने का एक बेहतर तरीका है। एक विकल्प क्या है जो तेज और अधिक सुन्न है?

यहाँ मेरा मजाक है:

def contains_nan( myarray ):
    """
    @param myarray : An n-dimensional array or a single float
    @type myarray : numpy.ndarray, numpy.array, float
    @returns: bool
    Returns true if myarray is numeric or only contains numeric values.
    Returns false if at least one non-numeric value exists
    Not-A-Number is given by the numpy.isnan() function.
    """
    return True

3
आपका विवरण contains_nanसंदिग्ध लग रहा है: "कम से कम एक गैर-संख्यात्मक मान मौजूद होने पर झूठे"। यदि सरणी में NaN होता है, तो मुझे contains_nanवापस लौटने की उम्मीद होगी True
सैमुअल तर्डियू

इनपुट्स के बारे में क्या array(['None', 'None'], dtype=object)? क्या इस तरह के इनपुट से सिर्फ एक अपवाद बढ़ सकता है?
फिन Finरूप नील्सन

उपयोग नहीं करते float('nan') in x। यह काम नहीं करता।
चार्ली पार्कर

जवाबों:


182

यह पुनरावृत्ति की तुलना में तेज़ होना चाहिए और आकार की परवाह किए बिना काम करेगा।

numpy.isnan(myarray).any()

संपादित करें: 30x तेज:

import timeit
s = 'import numpy;a = numpy.arange(10000.).reshape((100,100));a[10,10]=numpy.nan'
ms = [
    'numpy.isnan(a).any()',
    'any(numpy.isnan(x) for x in a.flatten())']
for m in ms:
    print "  %.2f s" % timeit.Timer(m, s).timeit(1000), m

परिणाम:

  0.11 s numpy.isnan(a).any()
  3.75 s any(numpy.isnan(x) for x in a.flatten())

बोनस: यह गैर-सरणी NumPy प्रकारों के लिए ठीक काम करता है:

>>> a = numpy.float64(42.)
>>> numpy.isnan(a).any()
False
>>> a = numpy.float64(numpy.nan)
>>> numpy.isnan(a).any()
True

1
सुन्न 1.7 के साथ समतल () संस्करण केवल दो बार पहले एक के रूप में तेजी से है
क्रिश्चियन गीयर

क्यों कुछ float('nan') in xकाम नहीं करता है? मैंने इसे आजमाया और अजगर ने Falseजहां रिटर्न दिया x = [1,2,3,float('nan')]
चार्ली पार्कर

1
@CharlieParker एक ही कारण है कि फ्लोट ('नेन') == फ्लोट ('नेन') फाल्स लौटेगा। NaN, NaN के बराबर नहीं है। यहाँ अधिक जानकारी: stackoverflow.com/questions/10034149/…
मपेट

1
@ mab: ऐसा इसलिए है क्योंकि numpy.anyएक जीनएक्सपी पर कॉल करने से जेनेक्सपी वापस आ जाता है; आप वास्तव में गणना नहीं कर रहे हैं जो आपको लगता है कि आप हैं। कभी भी numpy.anyएक जीनएक्सपी पर कॉल न करें ।
user2357112

वास्तविक डिबगिंग परिदृश्य में, मैं न्यूमेरिक ओवरफ्लो, अस्थिरता, आदि का पता लगाने के np.isfiniteबजाय देखने की भी सिफारिश करूंगाnp.isnan
बेन उस्मान

18

अगर अनंत संभव मूल्य है, तो मैं numpy.isfinite का उपयोग करूंगा

numpy.isfinite(myarray).all()

यदि उपरोक्त का मूल्यांकन किया जाता है True, तो myarrayइसमें कोई numpy.nan, numpy.infया -numpy.infमान शामिल नहीं है ।

numpy.nannumpy.infमूल्यों के साथ ठीक होगा , उदाहरण के लिए:

In [11]: import numpy as np

In [12]: b = np.array([[4, np.inf],[np.nan, -np.inf]])

In [13]: np.isnan(b)
Out[13]: 
array([[False, False],
       [ True, False]], dtype=bool)

In [14]: np.isfinite(b)
Out[14]: 
array([[ True, False],
       [False, False]], dtype=bool)

क्यों कुछ float('nan') in xकाम नहीं करता है? मैंने इसे आजमाया और अजगर ने Falseजहां रिटर्न दिया x = [1,2,3,float('nan')]
चार्ली पार्कर

1
@CharlieParker क्योंकि दो nanएस को एक दूसरे के बराबर नहीं माना जाता है। कोशिश करो float('nan') == float('nan')
अकवाल

दिलचस्प। उन्हें समान क्यों नहीं माना जाता है?
चार्ली पार्कर

1
@CharlieParker, मुझे नहीं लगता कि मैं यहां बहुत अच्छा जवाब दे सकता हूं। हो सकता है कि यह वही है जो आप के लिए देख रहे हैं: stackoverflow.com/questions/1565164/…
अकवाल

4

Pfft! माइक्रोसेकंड! कभी भी माइक्रोसेकंड में एक समस्या का समाधान नहीं किया जा सकता है जिसे नैनोसेकंड में हल किया जा सकता है।

ध्यान दें कि स्वीकृत उत्तर:

  • एक नान मिला है या नहीं, इसकी परवाह किए बिना पूरे डेटा पर निर्भर करता है
  • अस्थायी आकार N बनाता है, जो निरर्थक है।

एक बेहतर समाधान है जब एनएएन पाया जाता है तो तुरंत वापस लौटना:

import numba
import numpy as np

NAN = float("nan")

@numba.njit(nogil=True)
def _any_nans(a):
    for x in a:
        if np.isnan(x): return True
    return False

@numba.jit
def any_nans(a):
    if not a.dtype.kind=='f': return False
    return _any_nans(a.flat)

array1M = np.random.rand(1000000)
assert any_nans(array1M)==False
%timeit any_nans(array1M)  # 573us

array1M[0] = NAN
assert any_nans(array1M)==True
%timeit any_nans(array1M)  # 774ns  (!nanoseconds)

और n- आयामों के लिए काम करता है:

array1M_nd = array1M.reshape((len(array1M)/2, 2))
assert any_nans(array1M_nd)==True
%timeit any_nans(array1M_nd)  # 774ns

इसकी तुलना खस्ता देशी समाधान से करें:

def any_nans(a):
    if not a.dtype.kind=='f': return False
    return np.isnan(a).any()

array1M = np.random.rand(1000000)
assert any_nans(array1M)==False
%timeit any_nans(array1M)  # 456us

array1M[0] = NAN
assert any_nans(array1M)==True
%timeit any_nans(array1M)  # 470us

%timeit np.isnan(array1M).any()  # 532us

जल्दी निकलने की विधि 3 ऑर्डर या परिमाण गति (कुछ मामलों में) है। एक साधारण एनोटेशन के लिए भी जर्जर नहीं।


3

सुन्न 1.3 या svn के साथ आप ऐसा कर सकते हैं

In [1]: a = arange(10000.).reshape(100,100)

In [3]: isnan(a.max())
Out[3]: False

In [4]: a[50,50] = nan

In [5]: isnan(a.max())
Out[5]: True

In [6]: timeit isnan(a.max())
10000 loops, best of 3: 66.3 µs per loop

तुलनाओं में नान का उपचार पहले के संस्करणों में सुसंगत नहीं था।


क्यों कुछ float('nan') in xकाम नहीं करता है? मैंने इसे आजमाया और अजगर ने Falseजहां रिटर्न दिया x = [1,2,3,float('nan')]
चार्ली पार्कर

@CharlieParker ... क्योंकि NAN के साथ तुलना वह नहीं करती जो आप उम्मीद करते हैं। NAN को एक तार्किक NULL (= पता नहीं) की तरह माना जाता है। float("nan")==float("nan")देना False(हालांकि feasibly यह शायद नेन या कोई नहीं लौटना चाहिए)। इसी तरह NAN और बूलियन NULL के साथ विषमता SQL (जहां NULL = NULL कभी सत्य नहीं है) सहित कई भाषाओं में सच है।
184 बजे user48956

2

(np.where(np.isnan(A)))[0].shape[0]एक से अधिक हो जाएगा 0, तो Aकम से कम एक तत्व शामिल nan, Aएक हो सकता है n x mमैट्रिक्स।

उदाहरण:

import numpy as np

A = np.array([1,2,4,np.nan])

if (np.where(np.isnan(A)))[0].shape[0]: 
    print "A contains nan"
else:
    print "A does not contain nan"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.