पांडा: डेटा फ़्रेम को अनुक्रमित करते समय कई स्थितियाँ - अप्रत्याशित व्यवहार


135

मैं दो कॉलम में मानों द्वारा डेटाफ्रेम में पंक्तियों को फ़िल्टर कर रहा हूं।

किसी कारण के लिए OR ऑपरेटर व्यवहार करता है जैसे मैं अपेक्षा करता हूं और ऑपरेटर इसके विपरीत व्यवहार करता है।

मेरा परीक्षण कोड:

import pandas as pd

df = pd.DataFrame({'a': range(5), 'b': range(5) })

# let's insert some -1 values
df['a'][1] = -1
df['b'][1] = -1
df['a'][3] = -1
df['b'][4] = -1

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a != -1) | (df.b != -1)]

print pd.concat([df, df1, df2], axis=1,
                keys = [ 'original df', 'using AND (&)', 'using OR (|)',])

और परिणाम:

      original df      using AND (&)      using OR (|)    
             a  b              a   b             a   b
0            0  0              0   0             0   0
1           -1 -1            NaN NaN           NaN NaN
2            2  2              2   2             2   2
3           -1  3            NaN NaN            -1   3
4            4 -1            NaN NaN             4  -1

[5 rows x 6 columns]

जैसा कि आप देख सकते हैं, ANDऑपरेटर हर पंक्ति को गिराता है जिसमें कम से कम एक मान बराबर होता है -1। दूसरी ओर, ORऑपरेटर को -1उन्हें गिराने के लिए दोनों मूल्यों के बराबर होने की आवश्यकता होती है। मैं बिल्कुल विपरीत परिणाम की उम्मीद करूंगा। किसी को भी इस व्यवहार की व्याख्या कर सकते हैं, कृपया?

मैं पांडा का उपयोग कर रहा हूं 0.13.1।


1
df.queryऔर pd.evalइस उपयोग के मामले के लिए अच्छे फिट्स लगते हैं। pd.eval()कार्यों के परिवार, उनकी विशेषताओं और उपयोग के मामलों की जानकारी के लिए, कृपया pd.eval () का उपयोग करके पांडा में गतिशील अभिव्यक्ति मूल्यांकन पर जाएं ।
cs95

जवाबों:


211

जैसा कि आप देख सकते हैं, और ऑपरेटर हर पंक्ति को छोड़ देता है जिसमें कम से कम एक मान 1 के बराबर होता है। दूसरी ओर, OR ऑपरेटर को दोनों मानों को छोड़ने के लिए -1 के बराबर होना चाहिए।

ये सही है। याद रखें कि आप जिस चीज को रखना चाहते हैं, उसके संदर्भ में शर्त लिख रहे हैं , न कि आप जो गिराना चाहते हैं, उसके संदर्भ में। के लिए df1:

df1 = df[(df.a != -1) & (df.b != -1)]

आप कह रहे हैं "उन पंक्तियों को रखें जिनमें df.a-1 नहीं है और -1 df.bनहीं है", जो हर पंक्ति को छोड़ने के समान है जिसमें कम से कम एक मान -1 है।

के लिए df2:

df2 = df[(df.a != -1) | (df.b != -1)]

आप कह रहे हैं "पंक्तियों जिसमें या तो रखने df.aया df.bनहीं है -1" है, जो पंक्तियों जहां दोनों मान हैं -1 छोड़ने के समान है।

पुनश्च: जंजीर का उपयोग df['a'][1] = -1आपको परेशानी में डाल सकता है। यह का उपयोग करने का आदत में पाने के लिए बेहतर है .locऔर .iloc


24
DataFrame.query()यहाँ भी अच्छी तरह से काम करता है। df.query('a != -1 or b != -1')
फिलिप क्लाउड

5
जानकर लगता है कि पांडा क्यों चाहते हैं &और |अधिक andऔर or?
स्टोव

3
@stoves: सामान्य पायथन कोड में, andऔर orबुनियादी पायथन शब्दार्थ हैं जिन्हें संशोधित नहीं किया जा सकता है। &और |, दूसरी ओर, इसी तरह के विशेष तरीके हैं जो उनके व्यवहार को नियंत्रित करते हैं। (क्वेरी स्ट्रिंग्स में, निश्चित रूप से, हम अपनी पसंद के किसी भी पार्सिंग को लागू करने के लिए स्वतंत्र हैं।)
DSM

दिलचस्प है, ऐसा लगता है कि df[True & False]विफल रहता है, लेकिन df[(True) & (False)]सफल होता है (इस उदाहरण पर परीक्षण नहीं किया गया है)
3pitt

क्या कई लाइनों में इस तरह के वाक्यविन्यास को तोड़ना संभव होगा? सबसे PEP8 क्या होगा?
tommy.carstensen 22

41

आप क्वेरी () का उपयोग कर सकते हैं , अर्थात:

df_filtered = df.query('a == 4 & b != 2')

मेरे पास एक ऐसी स्थिति है जहां मुझे लगता है कि यह वाक्य रचना अधिक समझ में आता है जैसे: df.query ('= (a == 4 & b! = 2)। C == 3 ")
Aus_10

9

यहां थोड़ा गणितीय तर्क सिद्धांत :

"NOT a AND NOT b" , "NOT (a OR b)" के समान है , इसलिए:

"एक नहीं -1 और बी नहीं -1" "नहीं है (एक -1 या बी -1 है)" के बराबर है, जो "(ए -1 या बी -1 है) के विपरीत (पूरक) है "

इसलिए यदि आप सटीक विपरीत परिणाम चाहते हैं, तो df1 और df2 निम्नानुसार होना चाहिए:

df1 = df[(df.a != -1) & (df.b != -1)]
df2 = df[(df.a == -1) | (df.b == -1)]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.