एक श्रृंखला का सत्य मूल्य अस्पष्ट है। A.empty, a.bool (), a.item (), a.any () या a.all () का उपयोग करें


366

एक orशर्त के साथ मेरे परिणाम डेटाफ्रेम को फ़िल्टर करने में समस्या होना । मैं चाहता हूं कि मेरा परिणाम dfउन सभी स्तंभ varमानों को निकाले जो 0.25 से ऊपर और -0.25 से नीचे हैं।

नीचे दिया गया यह तर्क मुझे एक अस्पष्ट सत्य मूल्य देता है लेकिन यह तब काम करता है जब मैं इस फ़िल्टरिंग को दो अलग-अलग कार्यों में विभाजित करता हूं। यहाँ क्या हो रहा है? सुझाव का उपयोग करने के लिए निश्चित नहीं है a.empty(), a.bool(), a.item(),a.any() or a.all()

 result = result[(result['var']>0.25) or (result['var']<-0.25)]

46
|इसके बजाय का उपयोग करेंor
MaxU

1
यहाँ एक समाधान है:abs(result['var'])>0.25
कॉलिनमैक

जवाबों:


565

orऔर andअजगर बयानों की आवश्यकता होती है truth-values। के लिए pandasइन अस्पष्ट माना जाता है तो आप का उपयोग करना चाहिए "बिटवाइज़" |(या) या &(और) आपरेशन:

result = result[(result['var']>0.25) | (result['var']<-0.25)]

तत्व-वार or(या and) की उपज के लिए इस तरह के डेटास्ट्रक्चर के लिए इन्हें ओवरलोड किया जाता है ।


इस कथन में कुछ और स्पष्टीकरण जोड़ने के लिए:

अपवाद फेंक दिया जाता है जब आप प्राप्त करना चाहते हैं boolएक की pandas.Series:

>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

आपने जो मारा वह एक ऐसी जगह थी जहां ऑपरेटर ने ऑपरेंड को कथित रूप से परिवर्तित कर दिया bool(आपने उपयोग किया orलेकिन यह भी होता है and, ifऔर while):

>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

इन 4 बयान इसके अलावा वहाँ कई अजगर कार्यों कि कुछ छिपाने हैं boolकॉल (जैसे any, all, filter, ...) इन सामान्य रूप से नहीं के साथ समस्याग्रस्त हैं pandas.Seriesलेकिन पूर्णता के लिए मैं इन उल्लेख करना चाहता था।


आपके मामले में अपवाद वास्तव में मददगार नहीं है, क्योंकि इसमें सही विकल्पों का उल्लेख नहीं है । के लिए andऔर orआप उपयोग कर सकते हैं (यदि आप तत्व-वार तुलना चाहते हैं):

  • numpy.logical_or:

    >>> import numpy as np
    >>> np.logical_or(x, y)

    या बस |ऑपरेटर:

    >>> x | y
  • numpy.logical_and:

    >>> np.logical_and(x, y)

    या बस &ऑपरेटर:

    >>> x & y

यदि आप ऑपरेटरों का उपयोग कर रहे हैं, तो सुनिश्चित करें कि आप ऑपरेटर वरीयता के कारण अपने कोष्ठक को सही ढंग से सेट करते हैं ।

रहे हैं कई तार्किक numpy कार्यों जो चाहिए पर काम pandas.Series


अपवाद में उल्लिखित विकल्प अधिक अनुकूल हैं यदि आपने इसे करते समय सामना किया ifया while। मैं जल्द ही इनमें से प्रत्येक की व्याख्या करूँगा:

  • यदि आप जांचना चाहते हैं कि आपकी श्रृंखला खाली है या नहीं :

    >>> x = pd.Series([])
    >>> x.empty
    True
    >>> x = pd.Series([1])
    >>> x.empty
    False

    पाइथन सामान्य रूप lenसे कंटेनरों के समूह की व्याख्या करता है (जैसे list, tuple...) सत्य-मूल्य के रूप में अगर इसकी कोई स्पष्ट बूलियन व्याख्या नहीं है। इसलिए यदि आप अजगर जैसी जांच चाहते हैं, तो आप कर सकते हैं: if x.sizeया if not x.emptyइसके बजाय if x

  • अपने तो Seriesशामिल एक और केवल एक बूलियन मान:

    >>> x = pd.Series([100])
    >>> (x > 50).bool()
    True
    >>> (x < 50).bool()
    False
  • यदि आप अपनी श्रृंखला की पहली और एकमात्र वस्तु की जांच करना चाहते हैं (जैसे .bool()कि बूलियन सामग्री के लिए भी काम करता है):

    >>> x = pd.Series([100])
    >>> x.item()
    100
  • यदि आप जांचना चाहते हैं कि सभी या कोई वस्तु शून्य नहीं है, खाली नहीं है या गलत नहीं है:

    >>> x = pd.Series([0, 1, 2])
    >>> x.all()   # because one element is zero
    False
    >>> x.any()   # because one (or more) elements are non-zero
    True

पांडा श्रृंखला को संभालने के लिए इन अजगर संचालकों को ओवरलोड क्यों नहीं किया गया?
मुदित जैन

@MuditJain सीधे अधिभार के लिए कोई तरीका नहीं है and, orहै, और notअजगर में। ये ऑपरेटर सीधे boolउन ऑपरेशंस का उपयोग करते हैं जो ऑपरेंड पर वापस आते हैं। और एक तरह से पंडों / NumPy ने पहले से ही अधिक भार उठाया ValueErrorक्योंकि वे ऐसे डेटा संरचना के सत्य-मूल्य को अस्पष्ट मानते हैं।
MSeifert

समाधान ठीक है, लेकिन स्पष्टीकरण अच्छे से दूर है
अश्वेत

2
@blacksheep क्या आपके पास कोई सुझाव है जिसे मैंने बेहतर तरीके से समझाया है?
MSeifert

यह एक महान व्याख्या है। इसने वास्तव में मुझे बिटवाइज़ बनाम तार्किक को एक तरह से समझने में मदद की, जो कि अधिक अमूर्त उदाहरणों को करने में विफल रहे हैं।
रॉन्कवेव

41

बूलियन तर्क के लिए, का उपयोग करें &और |

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))

>>> df
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

यह देखने के लिए कि क्या हो रहा है, आपको प्रत्येक तुलना के लिए बूलियन का एक कॉलम मिलता है, जैसे

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool

जब आपके पास कई मापदंड होंगे, तो आपको कई कॉलम वापस मिल जाएंगे। यही कारण है कि ज्वाइन लॉजिक अस्पष्ट है। प्रत्येक स्तंभ का अलग-अलग उपयोग करना andया orव्यवहार करना , इसलिए आपको सबसे पहले उस कॉलम को एकल बूलियन मान पर कम करना होगा। उदाहरण के लिए, यह देखने के लिए कि क्या प्रत्येक स्तंभ में कोई मान या सभी मान सत्य हैं।

# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True

# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False

एक ही बात को प्राप्त करने का एक दृढ़ तरीका यह है कि इन सभी स्तंभों को एक साथ जोड़ दिया जाए, और उचित तर्क दिया जाए।

>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

अधिक विवरण के लिए, डॉक्स में बूलियन इंडेक्सिंग देखें ।


20

वैसे पंडों ने बिटवाइस और '' का उपयोग किया है। '' और प्रत्येक शर्त को '()' में लपेटा जाना चाहिए।

उदाहरण के लिए निम्नलिखित कार्य

data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]

लेकिन उचित कोष्ठक के बिना एक ही क्वेरी नहीं करता है

data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]

8

या, वैकल्पिक रूप से, आप ऑपरेटर मॉड्यूल का उपयोग कर सकते हैं। अधिक विस्तृत जानकारी यहाँ पायथन डॉक्स है

import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C > 0.25, df.C < -0.25)]

          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.4438

1

यह उत्कृष्ट उत्तर बहुत अच्छी तरह से समझाता है कि क्या हो रहा है और एक समाधान प्रदान करता है। मैं एक और समाधान जोड़ना चाहूंगा जो समान मामलों में उपयुक्त हो सकता है: queryविधि का उपयोग करना :

result = result.query("(var > 0.25) or (var < -0.25)")

Http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query भी देखें ।

(एक डेटाफ्रेम के साथ कुछ परीक्षण मैं वर्तमान में सुझाव के साथ काम कर रहा हूं कि यह विधि बूलियंस की श्रृंखला पर बिटवाइज़ ऑपरेटरों का उपयोग करने की तुलना में थोड़ी धीमी है: 2 एमएस बनाम 870 data)

चेतावनी का एक टुकड़ा : कम से कम एक स्थिति जहां यह सीधा नहीं होता है जब स्तंभ के नाम अजगर अभिव्यक्ति होते हैं। मेरे नाम में कॉलम थे WT_38hph_IP_2, WT_38hph_input_2और log2(WT_38hph_IP_2/WT_38hph_input_2)निम्नलिखित क्वेरी करना चाहते थे:"(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

मैंने निम्नलिखित अपवाद झरना प्राप्त किया:

  • KeyError: 'log2'
  • UndefinedVariableError: name 'log2' is not defined
  • ValueError: "log2" is not a supported function

मुझे लगता है कि ऐसा इसलिए हुआ क्योंकि क्वेरी पार्सर तीसरे कॉलम के नाम के साथ अभिव्यक्ति की पहचान करने के बजाय पहले दो कॉलम से कुछ बनाने की कोशिश कर रहा था।

एक संभावित समाधान यहां प्रस्तावित है


1

मुझे एक ही त्रुटि का सामना करना पड़ा और कुछ दिनों के लिए एक pyspark डेटाफ़्रेम के साथ ठप हो गया, मैं 0 के साथ ना मानों को भरकर इसे सफलतापूर्वक हल करने में सक्षम था क्योंकि मैं 2 फ़ील्ड से पूर्णांक मानों की तुलना कर रहा था।

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