पंडों से जटिल मानदंडों के साथ चयन करना। DataFrame


234

उदाहरण के लिए मेरे पास साधारण DF है:

import pandas as pd
from random import randint

df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)],
                   'B': [randint(1, 9)*10 for x in xrange(10)],
                   'C': [randint(1, 9)*100 for x in xrange(10)]})

क्या मैं 'ए' से मूल्यों का चयन कर सकता हूं, जिसके लिए 'बी' के लिए संबंधित मान 50 से अधिक होंगे, और 'सी' के लिए - पंडों के तरीकों और मुहावरों का उपयोग करते हुए 900 के बराबर नहीं?


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

साथ ही @Gecko का उत्तर देखें: stackoverflow.com/questions/13611065/…
निकोलस हम्फ्री

जवाबों:


390

ज़रूर! सेट अप:

>>> import pandas as pd
>>> from random import randint
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in range(10)],
                   'B': [randint(1, 9)*10 for x in range(10)],
                   'C': [randint(1, 9)*100 for x in range(10)]})
>>> df
   A   B    C
0  9  40  300
1  9  70  700
2  5  70  900
3  8  80  900
4  7  50  200
5  9  30  900
6  2  80  700
7  2  80  400
8  5  80  300
9  7  70  800

हम कॉलम संचालन को लागू कर सकते हैं और बूलियन श्रृंखला वस्तुएँ प्राप्त कर सकते हैं:

>>> df["B"] > 50
0    False
1     True
2     True
3     True
4    False
5    False
6     True
7     True
8     True
9     True
Name: B
>>> (df["B"] > 50) & (df["C"] == 900)
0    False
1    False
2     True
3     True
4    False
5    False
6    False
7    False
8    False
9    False

[अद्यतन, नई शैली पर स्विच करने के लिए .loc]:

और फिर हम ऑब्जेक्ट में इंडेक्स करने के लिए इनका उपयोग कर सकते हैं। रीड एक्सेस के लिए, आप इंडेक्स को चेन कर सकते हैं:

>>> df["A"][(df["B"] > 50) & (df["C"] == 900)]
2    5
3    8
Name: A, dtype: int64

लेकिन लेखन की पहुंच के लिए ऐसा करने वाले एक दृश्य और कॉपी के बीच अंतर के कारण आप खुद को परेशानी में डाल सकते हैं। आप .locइसके बजाय उपयोग कर सकते हैं :

>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"]
2    5
3    8
Name: A, dtype: int64
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"].values
array([5, 8], dtype=int64)
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] *= 1000
>>> df
      A   B    C
0     9  40  300
1     9  70  700
2  5000  70  900
3  8000  80  900
4     7  50  200
5     9  30  900
6     2  80  700
7     2  80  400
8     5  80  300
9     7  70  800

ध्यान दें कि मैंने गलती से टाइप किया == 900और नहीं != 900, या ~(df["C"] == 900), लेकिन मैं इसे ठीक करने के लिए बहुत आलसी हूं। पाठक के लिए व्यायाम करें। : ^)


5
.locअपडेट के बारे में - यदि आप स्पष्ट करें कि हमें एक कॉपी कहां मिलेगी और एक दृश्य कहां मिलेगा तो अच्छा होगा।
गिल बेट्स

3
क्या एक पांडा डेटाफ्रेम को फ़िल्टर करना और OR ऑपरेटर का उपयोग करना संभव है। उदाहरण के लिए यदि कोई स्तंभ महीना था, तो क्या आप df = data ['month' == JAN OR 'माह' == FEEN] कह सकते हैं? और शायद क्वेरी को और अधिक जटिल बनाते हुए एक नया कॉलम शामिल करें, newdf जहाँ col_month = jan or feb और col_day = MONDAY या WENDNESDAY
yoshiserry

7
@ योशिसेरी: कृपया इसे एक अलग प्रश्न के रूप में पूछें। पुराने उत्तर पर टिप्पणियों में कोई भी इसे यहां नहीं देखेगा।
DSM

2
कोष्ठक को मत भूलना - आपको अजीब त्रुटियाँ {TypeError}cannot compare a dtyped [int64] array with a scalar of type [bool]
मिलेंगी

क्या कोष्ठक के इस प्रयोग से पूरी श्रृंखला की गणना नहीं हो सकती है? क्या होगा अगर हम दक्षता के लिए बार-बार कम करना चाहते हैं?
ifly6

56

एक अन्य उपाय क्वेरी विधि का उपयोग करना है :

import pandas as pd

from random import randint
df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)],
                   'B': [randint(1, 9) * 10 for x in xrange(10)],
                   'C': [randint(1, 9) * 100 for x in xrange(10)]})
print df

   A   B    C
0  7  20  300
1  7  80  700
2  4  90  100
3  4  30  900
4  7  80  200
5  7  60  800
6  3  80  900
7  9  40  100
8  6  40  100
9  3  10  600

print df.query('B > 50 and C != 900')

   A   B    C
1  7  80  700
2  4  90  100
4  7  80  200
5  7  60  800

अब यदि आप कॉलम A में दिए गए मानों को बदलना चाहते हैं तो आप उनके सूचकांक को बचा सकते हैं:

my_query_index = df.query('B > 50 & C != 900').index

.... और .ilocउन्हें बदलने के लिए उपयोग करें अर्थात्:

df.iloc[my_query_index, 0] = 5000

print df

      A   B    C
0     7  20  300
1  5000  80  700
2  5000  90  100
3     4  30  900
4  5000  80  200
5  5000  60  800
6     3  80  900
7     9  40  100
8     6  40  100
9     3  10  600

12

और कोष्ठक का उपयोग करना याद रखें!

ध्यान रखें कि &ऑपरेटर जैसे >या <आदि के लिए ऑपरेटरों पर एक पूर्वता लेता है यही कारण है कि

4 < 5 & 6 > 4

का मूल्यांकन करता है False। इसलिए यदि आप उपयोग कर रहे हैं pd.loc, तो आपको अपने तार्किक विवरणों के साथ कोष्ठक लगाने की आवश्यकता है, अन्यथा आपको एक त्रुटि मिलती है। इसीलिए करते हैं:

df.loc[(df['A'] > 10) & (df['B'] < 15)]

के बजाय

df.loc[df['A'] > 10 & df['B'] < 15]

जिसके परिणामस्वरूप होगा

TypeError: dtyped की तुलना नहीं कर सकते


3

आप पंडों का उपयोग कर सकते हैं, यह तुलना के लिए कुछ कार्यों में बनाया गया है। इसलिए यदि आप "ए" के मानों का चयन करना चाहते हैं जो "बी" और "सी" की शर्तों से मिलते हैं (यह मानते हुए कि आप डेटाफ्रेम पांडा ऑब्जेक्ट वापस चाहते हैं)

df[['A']][df.B.gt(50) & df.C.ne(900)]

df[['A']] आपको DataFrame प्रारूप में कॉलम A वापस देगा।

पांडा 'जीई' फ़ंक्शन कॉलम बी के पदों को लौटाएगा जो 50 से अधिक हैं और 'ने' पदों को 900 के बराबर नहीं लौटाएगा।

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