पांडा: डेटाफ़्रेम की पंक्तियों पर जटिल फ़िल्टर


85

मैं प्रत्येक पंक्ति के एक फ़ंक्शन द्वारा पंक्तियों को फ़िल्टर करना चाहूंगा, जैसे

def f(row):
  return sin(row['velocity'])/np.prod(['masses']) > 5

df = pandas.DataFrame(...)
filtered = df[apply_to_all_rows(df, f)]

या एक और अधिक जटिल, आकस्मिक उदाहरण के लिए,

def g(row):
  if row['col1'].method1() == 1:
    val = row['col1'].method2() / row['col1'].method3(row['col3'], row['col4'])
  else:
    val = row['col2'].method5(row['col6'])
  return np.sin(val)

df = pandas.DataFrame(...)
filtered = df[apply_to_all_rows(df, g)]

ऐसा मैं किस प्रकार करूं?

जवाबों:


121

आप इसका उपयोग कर सकते हैं DataFrame.apply, जो किसी दिए गए अक्ष के साथ एक फ़ंक्शन लागू करता है,

In [3]: df = pandas.DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c'])

In [4]: df
Out[4]: 
          a         b         c
0 -0.001968 -1.877945 -1.515674
1 -0.540628  0.793913 -0.983315
2 -1.313574  1.946410  0.826350
3  0.015763 -0.267860 -2.228350
4  0.563111  1.195459  0.343168

In [6]: df[df.apply(lambda x: x['b'] > x['c'], axis=1)]
Out[6]: 
          a         b         c
1 -0.540628  0.793913 -0.983315
2 -1.313574  1.946410  0.826350
3  0.015763 -0.267860 -2.228350
4  0.563111  1.195459  0.343168

15
applyइस स्थिति में कोई जरूरत नहीं है। एक नियमित बूलियन इंडेक्स ठीक काम करेगा। df[df['b] > df['c']]। ऐसी बहुत कम स्थितियाँ हैं जिनकी वास्तव में आवश्यकता होती है applyऔर कुछ के साथ भी इसकी आवश्यकता होती हैaxis=1
टेड पेट्रोउ

@TedPetrou क्या होगा अगर आपका यह सुनिश्चित न हो कि आपके डेटाफ्रेम का प्रत्येक तत्व सही प्रकार का है। क्या एक नियमित बूलियन इंडेक्स अपवाद को संभालने का समर्थन करता है?
डी। रोर

13

मान लीजिए कि मेरे पास एक DataFrame इस प्रकार था:

In [39]: df
Out[39]: 
      mass1     mass2  velocity
0  1.461711 -0.404452  0.722502
1 -2.169377  1.131037  0.232047
2  0.009450 -0.868753  0.598470
3  0.602463  0.299249  0.474564
4 -0.675339 -0.816702  0.799289

मैं बूलियन मास्क बनाने के लिए पाप और DataFrame.prod का उपयोग कर सकता हूं:

In [40]: mask = (np.sin(df.velocity) / df.ix[:, 0:2].prod(axis=1)) > 0

In [41]: mask
Out[41]: 
0    False
1    False
2    False
3     True
4     True

फिर DataFrame से चयन करने के लिए मास्क का उपयोग करें:

In [42]: df[mask]
Out[42]: 
      mass1     mass2  velocity
3  0.602463  0.299249  0.474564
4 -0.675339 -0.816702  0.799289

2
वास्तव में, यह संभवतः एक बुरा उदाहरण था: np.sinसभी तत्वों को स्वचालित रूप से प्रसारित करता है। क्या होगा अगर मैंने इसे एक कम बुद्धिमान फ़ंक्शन के साथ बदल दिया जो केवल एक बार में एक इनपुट को संभाल सकता है?
डकवर्थ


5

मैं डकवर्थ के जवाब पर टिप्पणी नहीं कर सकता , लेकिन यह पूरी तरह से काम नहीं कर रहा है। डेटाफ्रेम खाली होने पर यह क्रैश हो जाता है:

df = pandas.DataFrame(columns=['a', 'b', 'c'])
df[df.apply(lambda x: x['b'] > x['c'], axis=1)]

आउटपुट:

ValueError: Must pass DataFrame with boolean values only

मेरे लिए यह पंडों में एक बग जैसा दिखता है, क्योंकि {} निश्चित रूप से बूलियन मूल्यों का एक वैध सेट है। एक समाधान के लिए रॉय ह्यूनजिन हान के जवाब का उल्लेख करें ।


3

सबसे अच्छा तरीका मुझे मिला है, बजाय reduce=Trueखाली डीएफ के लिए त्रुटियों से बचने के लिए उपयोग करने के बजाय (क्योंकि यह arg वैसे भी पदावनत है), बस फ़िल्टर को लागू करने से पहले उस df आकार> 0 की जांच करें:

def my_filter(row):
    if row.columnA == something:
        return True

    return False

if len(df.index) > 0:
    df[df.apply(my_filter, axis=1)]

0

आप locसंपत्ति का उपयोग आप डेटाफ्रेम स्लाइस के लिए कर सकते हैं ।

प्रलेखन के अनुसार , locएक callable functionतर्क हो सकता है।

In [3]: df = pandas.DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c'])

In [4]: df
Out[4]: 
          a         b         c
0 -0.001968 -1.877945 -1.515674
1 -0.540628  0.793913 -0.983315
2 -1.313574  1.946410  0.826350
3  0.015763 -0.267860 -2.228350
4  0.563111  1.195459  0.343168

# define lambda function
In [5]: myfilter = lambda x: x['b'] > x['c']

# use my lambda in loc
In [6]: df1 = df.loc[fif]

यदि आप अपने फ़िल्टर फ़ंक्शन fifको अन्य फ़िल्टर मानदंडों के साथ संयोजित करना चाहते हैं

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