我有一种情况,只有在数据框不为空时才需要向前移动数据框。如下图所示:
----- Filter 1 -------
Check if df.empty then return emptydf
else
----- Filter 2 ------
Check if df.empty then return emptydf
else
----- Filter 3 ------
return df
以上代码如下(只是一部分代码):
def filter_df(df):
df = df[df.somecolumn > 2].copy()
if df.empty:
return df
df = df[df.someother == 2].copy()
if df.empty:
return df
df = df[df.all <= 10].copy()
return df
如果我有很多这样的过滤器,它们期望数据帧不为空,那么我需要在每个过滤器之后检查为空。有没有比在每个级别检查数据框为空更好的方法了?
答案 0 :(得分:1)
重复设置数据框非常昂贵。重复复制数据框也可能很昂贵。预计算大量布尔掩码也很昂贵。棘手的部分是找到一种在for
循环中懒惰地应用蒙版的方法。
尽管以下功能解决方案看起来很丑陋,但确实可以解决上述问题。想法是将布尔掩码与聚合掩码迭代地组合。在循环中检查您的 mask 是否具有所有False
值,而不是数据框是否为空。在逻辑末尾应用汇总掩码一次:
from operator import methodcaller
def filter_df(df):
masks = [('somecolumn', 'gt', 2),
('someother', 'eq', 2),
('all', 'le', 10)]
agg_mask = np.ones(len(df.index)).astype(bool) # "all True" mask
for col, op, val in masks:
mask = methodcaller(op, val)(df[col])
agg_mask = agg_mask & mask
if not agg_mask.any():
return df[agg_mask]
return df[agg_mask]
此解决方案的注释系列比较运算符,例如>
,==
,<=
具有功能等效项pd.Series.gt
,pd.Series.eq
,pd.Series.le
。
答案 1 :(得分:-2)
您可以使用函数并在非常过滤后调用它
def check_empty(df):
if df.empty:
return df
df = df[df.somecolumn > 2].copy()
check_empty(df)
df = df[df.someother == 2].copy()
check_empty(df)
df = df[df.all <= 10].copy()
return df