পান্ডাস: ডেটাফ্রেমের সারিগুলিতে জটিল ফিল্টার


87

আমি প্রতিটি সারির ক্রিয়াকলাপ দ্বারা সারিগুলি ফিল্টার করতে চাই eg

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)]

আমি কীভাবে এটি করতে পারি?

উত্তর:


123

আপনি এটি ব্যবহার করে এটি করতে পারেন 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

16
applyএই পরিস্থিতিতে কোন প্রয়োজন নেই । একটি নিয়মিত বুলিয়ান সূচক ঠিক কাজ করবে। df[df['b] > df['c']]। এমন খুব কম পরিস্থিতি রয়েছে applyaxis=1
যাগুলির

@ টেডপেট্রো কী হবে যদি আপনার যদি নিশ্চিত না হয় যে আপনার ডেটাফ্রেমের প্রতিটি উপাদান সঠিক ধরণের। একটি নিয়মিত বুলিয়ান সূচক ব্যতিক্রম হ্যান্ডলিং সমর্থন করে?
ডি রোর

13

মনে করুন নীচে আমার একটি ডেটা ফ্রেম রয়েছে:

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

আমি বুলিয়ান মাস্ক তৈরি করতে পাপ এবং ডেটাফ্রেম.প্রড ব্যবহার করতে পারি:

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

তারপরে ডেটাফ্রেম থেকে নির্বাচন করতে মুখোশটি ব্যবহার করুন:

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

4
আসলে, এটি সম্ভবত একটি খারাপ উদাহরণ ছিল: 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

আমার কাছে এটি পান্ডাগুলির বাগের মতো দেখাচ্ছে, যেহেতু {defin অবশ্যই বুলিয়ান মানগুলির একটি বৈধ সেট set একটি সমাধানের জন্য রায় হিউঞ্জিন হানের উত্তর দেখুন


3

reduce=Trueখালি ডিএফের জন্য ত্রুটিগুলি এড়াতে ব্যবহার করার পরিবর্তে আমি যে সর্বোত্তম পন্থা পেয়েছি তা হ'ল (যেহেতু এই যুক্তিটি হ্রাস করা হয়), ফিল্টার প্রয়োগ করার আগে কেবল সেই ডিএফ আকার> 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)]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.