python 中嵌套循环的替代方案

问题描述 投票:0回答:1

我需要一个嵌套循环的替代方案,它在我的代码中花费了太多的时间复杂度。

我对编程比较陌生,正在使用包含以下数据的代码:

  • 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 有 30k 行和 3 列:'key', 'id', 'expiration_date'.
  • 一个空数据框time_machine,包含“key”、“id”、“simulated_date”和“status”列。

如果我只处理 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)
python python-3.x pandas nested-loops
1个回答
0
投票

样本数据

>>> 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
© www.soinside.com 2019 - 2024. All rights reserved.