pandas groupby fill bfill 需要中间groupby?

问题描述 投票:0回答:2

我试图通过对一列进行分组,然后对组内的列子集进行洪水填充(bfill().ffill())来掩盖数据框中丢失的数据。

我之前用过

def ffbf(x):
   return x.ffill().bfill()

df[some_cols] = df.groupby(group_key)[some_cols].transform(ffbf)

但即使在相对较小的数据帧上,变换也会变得令人难以置信慢(只有 3000x20 已经有几秒钟了),所以我想看看是否可以将 ffill 和 bfill 直接应用于组,因为它们现在应该被 cythonized。

我认为我需要在 ffill 和 bfill 之间再次调用 groupby 是否正确,因为这两种方法都不会保留分组?

现在我有

df[some_cols] = df[some_cols].groupby(group_key).ffill().groupby(group_key).bfill()

而且我认为它正在做我想做的事情,而且它比使用变换快得多,但我对熊猫的经验还不够确定,所以我想我会问。

[编辑] 看来此更改使我的数据变得混乱。为什么?

python pandas dataframe pandas-groupby
2个回答
3
投票

我认为这里有必要使用另一个

groupby
bfill
以避免仅将
NaN
组替换为另一个组。
为了提高性能,使用此代码:

NaN

In [205]: %timeit df1[some_cols] = df1.groupby(group_key)[some_cols].transform(ffbf)
443 ms ± 7.26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [206]: %timeit df[[group_key] + some_cols] = df[[group_key] + some_cols].groupby(group_key).ffill().groupby(group_key).bfill()
5.69 ms ± 31.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

编辑:在下一个 pandas 版本(测试 pandas 1.1.1)中可以使用:

np.random.seed(785) N = 10000 df = pd.DataFrame({'key':np.random.randint(1000, size=N), 'A':np.random.choice([1,2,np.nan], size=N), 'B':np.random.choice([1,4,np.nan], size=N), 'C':np.random.choice([7,0,np.nan], size=N), 'D':np.random.choice([7,0,8], size=N)}) df = df.sort_values('key') print (df) def ffbf(x): return x.ffill().bfill() group_key = 'key' some_cols = ['A','B','C'] df1 = df.copy() df1[some_cols] = df1.groupby(group_key)[some_cols].transform(ffbf) #a bit chamgef solution for working in pandas 0.23.1 df[[group_key] + some_cols] = df[[group_key] + some_cols].groupby(group_key).ffill().groupby(group_key).bfill() print (df.equals(df1)) True



0
投票

df[[group_key] + some_cols] = df[[group_key] + some_cols].groupby(df[group_key]).ffill().groupby(df[group_key]).bfill()

输出:

import numpy as np import pandas as pd from platform import python_version print(python_version()) print(pd.__version__) np.random.seed(785) N = 10000 df = pd.DataFrame({'key1':np.random.randint(30, size=N), 'key2':np.random.randint(30, size=N), 'A':np.random.choice([1,2,np.nan], size=N), 'B':np.random.choice([1,4,np.nan], size=N), 'C':np.random.choice([7,0,np.nan], size=N), 'D':np.random.choice([7,0,8], size=N)}) df = df.sort_values(['key1', 'key2']) def ffbf(x): return x.ffill().bfill() group_keys = ['key1', 'key2'] some_cols = ['A','B','C'] df1 = df.copy() df2 = df.copy() # slow method df1[some_cols] = df1.groupby(group_keys)[some_cols].transform(ffbf) # fast method gidx = df2.groupby(group_keys, sort=False).ngroup() df2 = df2.groupby(gidx).ffill().groupby(gidx).bfill() print (df2.equals(df1)) import timeit slow = """dfn = df.groupby(group_keys)[some_cols].transform(ffbf)""" print(timeit.timeit(slow, globals=globals(), number=20)) fast = """gidx = df.groupby(group_keys, sort=False).ngroup() dfn = df.groupby(gidx).ffill().groupby(gidx).bfill()""" print(timeit.timeit(fast, globals=globals(), number=20))

© www.soinside.com 2019 - 2024. All rights reserved.