Python Pandas 用 if 语句填充?
Python Pandas ffill with if statement?
我有以下时间序列测量两列中起点和终点之间的变化。我想在记录从开始到结束的路径的 Pandas 中使用矢量化方法而不是迭代来计算列 l
。有没有简单的方法来计算列? ffill()
和其他填充技术似乎天真地没有解决起始位置和结束位置之间的空白。有什么方法可以调节 ffill/bfill
来帮助解决这个问题吗?
注:s
和e
分别对应起始位置和结束位置。我想构建一个序列,其中 l
仅在 s
和 e
位置之间但不包括开始位置(并且不包括没有开始和结束的地方)。
示例如下,第 0-2 行我们要用 l
填充,但不包括第一行。还要确保在我们有另一个 s
.
之后我们没有行
s e l
0 1.0 NaN NaN
1 NaN NaN 1.0
2 NaN 1.0 1.0
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 1.0 NaN NaN
8 1.0 1.0 1.0
9 1.0 1.0 1.0
10 1.0 1.0 1.0
11 NaN 1.0 1.0
12 NaN NaN NaN
13 NaN NaN NaN
非常感谢您的帮助!
解决这些难以向量化问题的一个好方法是使用numba
。通过使用 numba
,代码被编译为 C-level
,因此这在大型数据帧上应该表现很好。通过在签名中指定 numba 类型,我们可以提前编译并进一步提高性能。这里我将输入类型设置为 float64
,对于另一个输入 dtype
相应地更改。
from numba import njit, float32
@njit('float32[:](float64[:,:])')
def ffill_conditional(a):
flag_col0 = 0
out = np.full(a.shape[0], fill_value=np.nan, dtype=float32)
for i in range(a.shape[0]):
if a[i,0]==1. and flag_col0==0:
flag_col0 = 1
from_col0 = i+1
elif a[i,1]==1 and np.isnan(a[i+1,1]) and flag_col0==1:
till_col1 = i+1
out[from_col0:till_col1] = 1.
flag_col0=0
return out
查看共享示例:
a = df.values[:,:2]
df['l'] = ffill_conditional(a)
print(df)
s e l
0 1.0 NaN NaN
1 NaN NaN 1.0
2 NaN 1.0 1.0
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 1.0 NaN NaN
8 1.0 1.0 1.0
9 1.0 1.0 1.0
10 1.0 1.0 1.0
11 NaN 1.0 1.0
12 NaN NaN NaN
13 NaN NaN NaN
我有以下时间序列测量两列中起点和终点之间的变化。我想在记录从开始到结束的路径的 Pandas 中使用矢量化方法而不是迭代来计算列 l
。有没有简单的方法来计算列? ffill()
和其他填充技术似乎天真地没有解决起始位置和结束位置之间的空白。有什么方法可以调节 ffill/bfill
来帮助解决这个问题吗?
注:s
和e
分别对应起始位置和结束位置。我想构建一个序列,其中 l
仅在 s
和 e
位置之间但不包括开始位置(并且不包括没有开始和结束的地方)。
示例如下,第 0-2 行我们要用 l
填充,但不包括第一行。还要确保在我们有另一个 s
.
s e l
0 1.0 NaN NaN
1 NaN NaN 1.0
2 NaN 1.0 1.0
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 1.0 NaN NaN
8 1.0 1.0 1.0
9 1.0 1.0 1.0
10 1.0 1.0 1.0
11 NaN 1.0 1.0
12 NaN NaN NaN
13 NaN NaN NaN
非常感谢您的帮助!
解决这些难以向量化问题的一个好方法是使用numba
。通过使用 numba
,代码被编译为 C-level
,因此这在大型数据帧上应该表现很好。通过在签名中指定 numba 类型,我们可以提前编译并进一步提高性能。这里我将输入类型设置为 float64
,对于另一个输入 dtype
相应地更改。
from numba import njit, float32
@njit('float32[:](float64[:,:])')
def ffill_conditional(a):
flag_col0 = 0
out = np.full(a.shape[0], fill_value=np.nan, dtype=float32)
for i in range(a.shape[0]):
if a[i,0]==1. and flag_col0==0:
flag_col0 = 1
from_col0 = i+1
elif a[i,1]==1 and np.isnan(a[i+1,1]) and flag_col0==1:
till_col1 = i+1
out[from_col0:till_col1] = 1.
flag_col0=0
return out
查看共享示例:
a = df.values[:,:2]
df['l'] = ffill_conditional(a)
print(df)
s e l
0 1.0 NaN NaN
1 NaN NaN 1.0
2 NaN 1.0 1.0
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 1.0 NaN NaN
8 1.0 1.0 1.0
9 1.0 1.0 1.0
10 1.0 1.0 1.0
11 NaN 1.0 1.0
12 NaN NaN NaN
13 NaN NaN NaN