我需要一个嵌套循环的替代方案,它在我的代码中花费了太多的时间复杂度。
我对编程比较陌生,正在使用包含以下数据的代码:
dates_list = ['2022-12-01', '2022-12-02', '2022-12-03', '2022-12-04', '2022-12-05', ... '2023-04-23', '2023-04-24', '2023-04-25']
如果我只处理 df 的前 300 行,我已经编写了一个运行良好的代码。然而,嵌套循环显然无法处理完整的数据框 df。 原始代码有很多 if-else,数据帧有更多列需要分析,但我将忽略它们,因为它们对嵌套循环问题并不重要。
我已经没有解决这个问题的可能性了,有谁知道可能的替代方案吗?
import pandas as pd
import datetime
file = '..\\Extrato.xlsx'
df = pd.read_excel(file) #columns: "key", "id", "expiration_date"
time_machine = pd.DataFrame(columns = ["key", "id", "simulated_date", 'status'])
date_a = datetime.datetime(2022, 12, 1)
date_z = datetime.datetime.today()
delta = date_z - date_a
dates_list = [(date_z - datetime.timedelta(days=i)).strftime('%Y-%m-%d') for i in range(delta.days,-1,-1)]
for i in dates_list:
for j, row in df.iterrows():
simulated_date = datetime.datetime.strptime(i, '%Y-%m-%d').date()
expiration_date = row['expiration_date'].date()
if expiration_date <= simulated_date:
new_row = {'key': row['key'], 'id': row['id'], 'simulated_date': simulated_date, 'status': 'ok',}
time_machine = time_machine.append(new_row, ignore_index=True)
样本数据
>>> time_machine = pd.DataFrame(columns = ["key", "id", "simulated_date", 'status'])
>>> df = pd.DataFrame({'key': ['key1', 'key2', 'key3'], 'id': ['id1', 'id2', 'id3'], 'expiration_date': ['2022-01-01', '2022-06-01', '2023-01-01']})
>>> df
key id expiration_date
0 key1 id1 2022-01-01
1 key2 id2 2022-06-01
2 key3 id3 2023-01-01
>>> data_list = ['2022-02-12', '2023-01-01', '2023-05-01']
为了使代码尽可能快,您需要减少循环的使用,使用日期时间类型可能会有所帮助(我们将能够使用日期时间操作):
data_list = pd.to_datetime(data_list)
df['expiration_date'] = pd.to_datetime(df['expiration_date'])
如果按日期排序
df
,内部循环可以大大减少(不需要多次执行 if 语句)。
>>> df = df.sort_values('expiration_date')
现在,我们只需要使用外层循环即可。
>>> for data in data_list:
... # There is no need to do a loop to look at each one individually.
... # As df is sorted, we also now that `values` will be also sorted.
... values = df.loc[df['expiration_date'] <= data]
... rows = {
... 'key': values['key'].to_list(),
... 'id': values['id'].to_list(),
... 'simulated_date': [data]*len(values),
... 'status': 'ok',
... }
... time_machine = pd.concat(time_machine, pd.DataFrame(rows))
>>> time_machine
key id simulated_date status
0 key1 id1 2022-02-12 ok
0 key1 id1 2023-01-01 ok
1 key2 id2 2023-01-01 ok
2 key3 id3 2023-01-01 ok
0 key1 id1 2023-05-01 ok
1 key2 id2 2023-05-01 ok
2 key3 id3 2023-05-01 ok