pandas:DataFrame的行上的复杂filter
我想通过每行的函数来过滤行,例如
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)]
我怎么能这样做?
你可以使用DataFrame.apply
来完成这个function,它沿给定的坐标轴应用一个函数,
In [3]: df = pandas.DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c']) In [4]: df Out[4]: abc 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]: abc 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
假设我有一个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来创build一个布尔掩码:
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中select:
In [42]: df[mask] Out[42]: mass1 mass2 velocity 3 0.602463 0.299249 0.474564 4 -0.675339 -0.816702 0.799289
我不能评论duckworthd的答案 ,但这并不完美。 dataframe为空时崩溃:
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
对我来说,它看起来像pandas中的一个错误,因为{}确实是一组有效的布尔值。
指定reduce=True
来处理空的DataFrame。
import pandas as pd t = pd.DataFrame(columns=['a', 'b']) t[t.apply(lambda x: x['a'] > 1, axis=1, reduce=True)]