我怎样才能提高这段代码的运行时间?
How could I improve the runtime of this code?
我想在两个数据帧之间共享一些信息。我的代码有效但需要很长时间。你知道我怎样才能改善我的 运行 时间吗?我正在尝试执行以下操作:
我有一个数据框 df1
(它有 160 列,但这里只有显示的列很重要):
a_idx b_idx c_idx d_idx e_idx f_idx Evt_ID
0 0 1 3 4 2 6 346642
1 1 2 3 4 5 5 917426
2 0 1 3 4 2 2 123543
...
还有一个数据框df2
(ist有10列,但这里只有这些很重要):
Name Evt_ID
0 Jet1 346642
1 Jet2 346642
2 Jet3 346642
3 Jet4 346642
4 Jet5 346642
5 Jet6 346642
6 Jet7 346642
7 Lepton 346642
8 Jet1 917426
9 Jet2 917426
...
现在我想要在 df2
中创建一个名为“y”的新列,其中包含每行的类别。该类别可以在 df1
的帮助下找到,类别是:
category_list = ["a", "b", "c", "d", "e", "f"]
也可以是"unknown"
。例如,df1 中的第一行具有值 category = [0,1,3,4,2,6]
,这意味着 df2
应如下所示:
(解释:第5数在category
中是2 --> Jet(2+1) = Jet3 在 category_list
中有 第五个 类别:"e")
Name Evt_ID y
0 Jet1 346642 a
1 Jet2 346642 b
2 Jet3 346642 e
3 Jet4 346642 c
4 Jet5 346642 d
5 Jet6 346642 unknown
6 Jet7 346642 f
7 Lepton 346642 unknown
...
我的实现方式如下:
df["y"] = "unknown"
category_list = ["a", "b", "c", "d", "e", "f"]
for event_id in tqdm(df1.Evt_ID):
category = df1.loc[df1.Evt_ID == event_id, ["a_idx","b_idx",
"c_idx", "d_idx",
"e_idx", "f_idx"]].values.squeeze()
i = 0
for jet_index in category:
df2.loc[(dfo.Evt_ID == event_id) & (dfo.Name == "Jet".join(str(jet_index+1))), "y"] = category_list[i]
i += 1
这段代码 运行 需要 30 或 60 分钟,具体取决于它 运行 进入的 jupyter 笔记本。为什么笔记本本身会影响 运行 时间?但更重要的是:如何改善 运行时间?
由于其矢量化结构,以下代码段应该 运行 更快。
这里有两个技巧。第一个是使用 df.melt
,它有效地将列 a
、b
、...、e
转换为行。第二个是 join
使用 df2
生成的 DataFrame。这样,所有缺失值都变成 NaN
并且可以用 unknown
和 df.fillna
.
替换
cols = ["a_idx", "b_idx", "c_idx", "d_idx", "e_idx", "f_idx"]
df = df1[cols + ["Evt_ID"]].rename(columns={c: c[0] for c in cols})
df = df.melt(id_vars="Evt_ID", var_name="y")
df["value"] = "Jet" + (df["value"] + 1).astype(str)
df = df2.join(df.set_index(["Evt_ID", "value"]), on=["Evt_ID", "Name"])
df = df.fillna("unknown")
最后,df
看起来像:
Name Evt_ID y
0 Jet1 346642 a
1 Jet2 346642 b
2 Jet3 346642 e
3 Jet4 346642 c
4 Jet5 346642 d
5 Jet6 346642 unknown
6 Jet7 346642 f
7 Lepton 346642 unknown
8 Jet1 917426 unknown
9 Jet2 917426 a
此结果是使用以下示例数据获得的:
import pandas as pd
df1 = pd.DataFrame(
[
[0, 1, 3, 4, 2, 6, 346642],
[1, 2, 3, 4, 5, 5, 917426],
[0, 1, 3, 4, 2, 2, 123543],
],
columns=["a_idx", "b_idx", "c_idx", "d_idx", "e_idx", "f_idx", "Evt_ID"],
)
df2 = pd.DataFrame(
[
["Jet1", 346642],
["Jet2", 346642],
["Jet3", 346642],
["Jet4", 346642],
["Jet5", 346642],
["Jet6", 346642],
["Jet7", 346642],
["Lepton", 346642],
["Jet1", 917426],
["Jet2", 917426],
],
columns=["Name", "Evt_ID"],
)
我想在两个数据帧之间共享一些信息。我的代码有效但需要很长时间。你知道我怎样才能改善我的 运行 时间吗?我正在尝试执行以下操作:
我有一个数据框 df1
(它有 160 列,但这里只有显示的列很重要):
a_idx b_idx c_idx d_idx e_idx f_idx Evt_ID
0 0 1 3 4 2 6 346642
1 1 2 3 4 5 5 917426
2 0 1 3 4 2 2 123543
...
还有一个数据框df2
(ist有10列,但这里只有这些很重要):
Name Evt_ID
0 Jet1 346642
1 Jet2 346642
2 Jet3 346642
3 Jet4 346642
4 Jet5 346642
5 Jet6 346642
6 Jet7 346642
7 Lepton 346642
8 Jet1 917426
9 Jet2 917426
...
现在我想要在 df2
中创建一个名为“y”的新列,其中包含每行的类别。该类别可以在 df1
的帮助下找到,类别是:
category_list = ["a", "b", "c", "d", "e", "f"]
也可以是"unknown"
。例如,df1 中的第一行具有值 category = [0,1,3,4,2,6]
,这意味着 df2
应如下所示:
(解释:第5数在category
中是2 --> Jet(2+1) = Jet3 在 category_list
中有 第五个 类别:"e")
Name Evt_ID y
0 Jet1 346642 a
1 Jet2 346642 b
2 Jet3 346642 e
3 Jet4 346642 c
4 Jet5 346642 d
5 Jet6 346642 unknown
6 Jet7 346642 f
7 Lepton 346642 unknown
...
我的实现方式如下:
df["y"] = "unknown"
category_list = ["a", "b", "c", "d", "e", "f"]
for event_id in tqdm(df1.Evt_ID):
category = df1.loc[df1.Evt_ID == event_id, ["a_idx","b_idx",
"c_idx", "d_idx",
"e_idx", "f_idx"]].values.squeeze()
i = 0
for jet_index in category:
df2.loc[(dfo.Evt_ID == event_id) & (dfo.Name == "Jet".join(str(jet_index+1))), "y"] = category_list[i]
i += 1
这段代码 运行 需要 30 或 60 分钟,具体取决于它 运行 进入的 jupyter 笔记本。为什么笔记本本身会影响 运行 时间?但更重要的是:如何改善 运行时间?
由于其矢量化结构,以下代码段应该 运行 更快。
这里有两个技巧。第一个是使用 df.melt
,它有效地将列 a
、b
、...、e
转换为行。第二个是 join
使用 df2
生成的 DataFrame。这样,所有缺失值都变成 NaN
并且可以用 unknown
和 df.fillna
.
cols = ["a_idx", "b_idx", "c_idx", "d_idx", "e_idx", "f_idx"]
df = df1[cols + ["Evt_ID"]].rename(columns={c: c[0] for c in cols})
df = df.melt(id_vars="Evt_ID", var_name="y")
df["value"] = "Jet" + (df["value"] + 1).astype(str)
df = df2.join(df.set_index(["Evt_ID", "value"]), on=["Evt_ID", "Name"])
df = df.fillna("unknown")
最后,df
看起来像:
Name Evt_ID y
0 Jet1 346642 a
1 Jet2 346642 b
2 Jet3 346642 e
3 Jet4 346642 c
4 Jet5 346642 d
5 Jet6 346642 unknown
6 Jet7 346642 f
7 Lepton 346642 unknown
8 Jet1 917426 unknown
9 Jet2 917426 a
此结果是使用以下示例数据获得的:
import pandas as pd
df1 = pd.DataFrame(
[
[0, 1, 3, 4, 2, 6, 346642],
[1, 2, 3, 4, 5, 5, 917426],
[0, 1, 3, 4, 2, 2, 123543],
],
columns=["a_idx", "b_idx", "c_idx", "d_idx", "e_idx", "f_idx", "Evt_ID"],
)
df2 = pd.DataFrame(
[
["Jet1", 346642],
["Jet2", 346642],
["Jet3", 346642],
["Jet4", 346642],
["Jet5", 346642],
["Jet6", 346642],
["Jet7", 346642],
["Lepton", 346642],
["Jet1", 917426],
["Jet2", 917426],
],
columns=["Name", "Evt_ID"],
)