如何矢量化 pandas 取决于前一行的代码?
How to vectorize pandas code where it depends on previous row?
我正在尝试矢量化 pandas 中的代码片段:
我有一个像这样生成的 pandas 数据框:
ids
ftest
值
0
Q52EG
0
0
1
Q52EG
0
1
2
Q52EG
1
2
3
Q52EG
1
3
4
Q52EG
1
4
5
QQ8Q4
0
5
6
QQ8Q4
0
6
7
QQ8Q4
1
7
8
QQ8Q4
1
8
9
QVIPW
1
9
如果 ids
列中的任何 id 在 ftest
列中的值为 1,则所有具有相同 id 的后续行在 has_hist
列中应标记为 1 并且它不依赖于当前的 ftest
值,如下面的数据框所示:
ids
ftest
值
has_hist
0
Q52EG
0
0
0
1
Q52EG
0
1
0
2
Q52EG
1
2
0
3
Q52EG
1
3
1
4
Q52EG
1
4
1
5
QQ8Q4
0
5
0
6
QQ8Q4
0
6
0
7
QQ8Q4
1
7
0
8
QQ8Q4
1
8
1
9
QVIPW
1
9
0
我正在使用这样的迭代方法来执行此操作:
previous_present = {}
has_prv_history = []
for index, value in id_df.iterrows():
my_id = value["ids"]
ftest_mentioned = value["ftest"]
previous_flag = 0
if my_id in previous_present.keys():
previous_flag = 1
elif (ftest_mentioned == 1):
previous_present[my_id] = 1
has_prv_history.append(previous_flag)
id_df["has_hist"] = has_prv_history
是否可以在不使用 apply
的情况下将此代码矢量化?
此类任务的两个关键函数是 shift
和 ffill
,按组应用。对于这个具体问题:
df2["has_hist"] = df.groupby("ids").ftest.shift().where(lambda s: s.eq(1))
df2["has_hist"] = df2.groupby("ids").has_hist.ffill().fillna(0).astype("int32")
这是 transform
的变体,但根据我的经验,它通常比“纯”Pandas 操作慢:
df2 = (
df
.groupby("ids")
.ftest.transform(
lambda s: (
s
.shift()
.where(lambda t: t.eq(1))
.ffill()
.fillna(0)
.astype("int32")
)
)
)
我正在尝试矢量化 pandas 中的代码片段:
我有一个像这样生成的 pandas 数据框:
ids | ftest | 值 | |
---|---|---|---|
0 | Q52EG | 0 | 0 |
1 | Q52EG | 0 | 1 |
2 | Q52EG | 1 | 2 |
3 | Q52EG | 1 | 3 |
4 | Q52EG | 1 | 4 |
5 | QQ8Q4 | 0 | 5 |
6 | QQ8Q4 | 0 | 6 |
7 | QQ8Q4 | 1 | 7 |
8 | QQ8Q4 | 1 | 8 |
9 | QVIPW | 1 | 9 |
如果 ids
列中的任何 id 在 ftest
列中的值为 1,则所有具有相同 id 的后续行在 has_hist
列中应标记为 1 并且它不依赖于当前的 ftest
值,如下面的数据框所示:
ids | ftest | 值 | has_hist | |
---|---|---|---|---|
0 | Q52EG | 0 | 0 | 0 |
1 | Q52EG | 0 | 1 | 0 |
2 | Q52EG | 1 | 2 | 0 |
3 | Q52EG | 1 | 3 | 1 |
4 | Q52EG | 1 | 4 | 1 |
5 | QQ8Q4 | 0 | 5 | 0 |
6 | QQ8Q4 | 0 | 6 | 0 |
7 | QQ8Q4 | 1 | 7 | 0 |
8 | QQ8Q4 | 1 | 8 | 1 |
9 | QVIPW | 1 | 9 | 0 |
我正在使用这样的迭代方法来执行此操作:
previous_present = {}
has_prv_history = []
for index, value in id_df.iterrows():
my_id = value["ids"]
ftest_mentioned = value["ftest"]
previous_flag = 0
if my_id in previous_present.keys():
previous_flag = 1
elif (ftest_mentioned == 1):
previous_present[my_id] = 1
has_prv_history.append(previous_flag)
id_df["has_hist"] = has_prv_history
是否可以在不使用 apply
的情况下将此代码矢量化?
此类任务的两个关键函数是 shift
和 ffill
,按组应用。对于这个具体问题:
df2["has_hist"] = df.groupby("ids").ftest.shift().where(lambda s: s.eq(1))
df2["has_hist"] = df2.groupby("ids").has_hist.ffill().fillna(0).astype("int32")
这是 transform
的变体,但根据我的经验,它通常比“纯”Pandas 操作慢:
df2 = (
df
.groupby("ids")
.ftest.transform(
lambda s: (
s
.shift()
.where(lambda t: t.eq(1))
.ffill()
.fillna(0)
.astype("int32")
)
)
)