[英]Faster way to forward-fill and back-fill a groupby
我想在ffill
之后填充和bfill
特定的列。
我的解决方案有效:
import numpy as np
import pandas as pd
df = pd.DataFrame({
"A": [1, 1, 1, 1, 2, 2, 2, 2],
"B": [np.nan, 'f1', 'b1', np.nan, np.nan, 'f2', 'b2', np.nan]
})
df['B'] = df.groupby('A')['B'].apply(lambda _: _.ffill().bfill())
所以这:
A B
0 1 NaN
1 1 f1
2 1 b1
3 1 NaN
4 2 NaN
5 2 f2
6 2 b2
7 2 NaN
变成这样:
A B
0 1 f1
1 1 f1
2 1 b1
3 1 b1
4 2 f2
5 2 f2
6 2 b2
7 2 b2
请注意,我要填充和 bfill 的序列将始终采用这种格式( Nan, x, y, Nan
)
虽然这可行,但在大型数据帧上速度非常慢。
我正在寻找一些优化以使其更快(理想情况下不使用 Dask 或多处理),也许我可以进行 Numpy 优化?
我没有很多运气看其他答案,比如这个。
如果你想要速度,避免 groupby 并使用 numpy 而不是 pandas 是很好的规则。 这通常是不可能的,但在这里你有非常规则的数据的特殊情况,你所需要的只是[start:end:stride]
形式的下标三元组:
df.iloc[0::4,1] = df.iloc[1::4,1].values
df.iloc[3::4,1] = df.iloc[2::4,1].values
说明:大多数人都知道您可以使用[start:stop]
形式的下标,但您也可以添加一个可选的stride
参数。 所以第一行说用元素 1,5,9,... 替换元素 0,4,8,... “值”是删除 pandas 索引所必需的,这实际上是有害的。
仅仅通过避免 groupby,这应该会更快一些。 For a little more speed, you could output column B to numpy, do work in numpy (basically the same code), and then reimport to pandas:
arr = df.B.values
arr[0::4] = arr[1::4]
arr[3::4] = arr[2::4]
df.B = arr
如果您想留在 pandas 中,您可以做的另一件事是取消堆叠,复制整个列,然后重新堆叠。 无论如何,这基本上就是上面的代码正在做的事情。 老实说,对于这样一个矩形问题,任何数组样式的方法都会相当快。
如果您的数据确实具有连续组的良好结构,那么您可以通过使用ffill
和bfill
中的limit
参数来避免groupby
,例如:
print (df['B'].ffill(limit=1).bfill(limit=1))
0 f1
1 f1
2 b1
3 b1
4 f2
5 f2
6 b2
7 b2
Name: B, dtype: object
如果你的格式是前缀为(Nan, x, y, Nan)
,什么时候可以做
df.B=df.groupby([df.A,df.index//2]).B.transform('first')
Out[169]:
B
0 f1
1 f1
2 b1
3 b1
4 f2
5 f2
6 b2
7 b2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.