我想通过每行的函数来过滤行,例如
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)]
我该怎么办?
答案 0 :(得分:103)
您可以使用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
沿给定轴应用函数
{{1}}
答案 1 :(得分:11)
假设我有一个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
我可以使用sin和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 :(得分:3)
指定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)]
答案 3 :(得分:2)
我对duckworthd's answer发表评论,但这并不完美。当数据帧为空时崩溃:
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
对我而言,它看起来像是熊猫中的一个错误,因为{}绝对是一组有效的布尔值。
答案 4 :(得分:0)
我发现的最佳方法是,而不是使用reduce=True
来避免出现空df的错误(因为无论如何该arg都已被弃用),只需在应用过滤器之前检查df size> 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)]
答案 5 :(得分:0)
您可以使用loc
属性对数据帧进行切片。
根据documentation,
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)]