我有两个数据框,df 和 ct
df:UNIT, START, END, CHECK
是相关列。 CHECK 值均默认为“n”。我的代码测试它们,如果它们通过,则将此值更改为 'y'
df.shape = 59155, 5
单位 | DTours | 开始 | END | 检查 | |
---|---|---|---|---|---|
0 | A7000 | 0.1097 | 43100.0321 | 43382.1417 | n |
1 | A7000 | 0.0125 | 43105.6621 | 43382.6736 | n |
2 | A7000 | 0.2042 | 43200.1214 | 43388.3465 | n |
3 | A7000 | 0.1521 | 43389.2979 | 43854.4500 | n |
4 | A7002 | 0.1455 | 44198.5049 | 44199.0009 | n |
ct:UNIT, START, END
是唯一的组合,但每个 UNIT 可以有多个条目(这些实际上是开始/结束日期)。平均每个 UNIT 行重复约 5 次
ct.shape = 6219, 3
单位 | 开始 | END | |
---|---|---|---|
0 | A7000 | 43101 | 43156 |
1 | A7000 | 43101 | 43173 |
2 | A7000 | 43172 | 43616 |
3 | A7000 | 43172 | 43712 |
4 | A7002 | 43172 | 44196 |
我正在测试 df['START'] 和 df['END '] 值是否在 ct 中该 UNIT 的任何实例之间。然而,代码花费的时间特别长。它在 12 小时内迭代了约 12000 行。我做错了什么?
伪代码:
for loop iterating through all rows of df
create list of all cf[START] values for current df[UNIT]
create list of all cf[END] values for current df[UNIT]
test if the df[CHECK] value is 'n' viz default value
for loop iterating over length of cf[START] (len = cf[END]), index
test if (df[START]>= cf[START][index]) AND (df[END]>= cf[END][index])
change df[CHECK] to 'y'
break for loop iterating over cf[START] for this row in df
实际代码:
for index, row in df.iterrows():
display.clear_output(wait=True)
display.display(plt.gcf())
df_unit = row['UNIT']
ct_start = ct.loc[ct['UNIT'] == df_unit]['START'].values
ct_end = ct.loc[ct['UNIT'] == df_unit]['END'].values
if (row['UNIT'] != 'y'):
for ct_index in range(len(ct_start)):
if ((row['START'] >= ct_start[ct_index]) & (row['END'] <=
ct_end[ct_index])):
row['CHECK'] == 'y'
aaa += 1
break
plt.scatter(index,aaa, c='r')
上述数据帧的预期输出
单位 | DTours | 开始 | END | 检查 | |
---|---|---|---|---|---|
0 | A7000 | 0.1097 | 43100.0321 | 43382.1417 | n |
1 | A7000 | 0.0125 | 43105.6621 | 43382.6736 | n |
2 | A7000 | 0.2042 | 43200.1214 | 43388.3465 | y |
3 | A7000 | 0.1521 | 43389.2979 | 43854.4500 | n |
4 | A7002 | 0.1455 | 44198.5049 | 44199.0009 | n |
答案 0 :(得分:1)
根据经验:90% 的情况下,如果您在数据帧上使用循环,那么您做错了
就你而言:
for ... if
,不如过滤数据框:df[df["CHECK"] == "y"]
ct
数据框。您最好将此数据框分组一次并将其转换为您可以按单元访问的字典:
units = dict(list(ct.groupby("UNIT")))
for index in units[df_unit]: do_something()
这应该已经大大提高了性能
答案 1 :(得分:0)
我们可以使用以下步骤来解决这个问题
df
上用merge
重置ct
和UNIT
的索引START
和 END
中的对应值满足包含条件的索引loc
的布尔索引,使用在上一步中获得的索引将 CHECK
列中的值更新为 y
s = df.reset_index().merge(ct, on='UNIT', suffixes=['', '_r'])
ix = s.query("START >= START_r and END <= END_r")['index']
df.loc[df.index.isin(ix), 'CHECK'] = 'y'
UNIT DTHours START END CHECK
0 A7000 0.1097 43100.0321 43382.1417 n
1 A7000 0.0125 43105.6621 43382.6736 n
2 A7000 0.2042 43200.1214 43388.3465 y
3 A7000 0.1521 43389.2979 43854.4500 n
4 A7002 0.1455 44198.5049 44199.0009 n