Меня удивляет, как медленно инициализируется пустой объект pandas данных:
import pandas as pd
from utils import Timer
with Timer.Timer("test"):
with Timer.Timer("set"):
columns = pd.DatetimeIndex(['2018-02-12', '2018-03-12', '2018-04-10', '2018-07-10','2019-01-10', '2020-01-10', '2021-01-10', '2022-01-10',
'2023-01-10', '2024-01-10', '2025-01-10', '2026-01-10', '2027-01-10', '2028-01-10', '2030-01-10', '2033-01-10',
'2038-01-10', '2043-01-10', '2048-01-10'],dtype='datetime64[ns]', name='maturity', freq=None)
flowKeys = ["flowType", "flowDate"]
rate = 2/100
date2 = datetime(2020,1,1)
date1 = datetime(2000,1,1)
#dataframes
flows = None
dNDF = None
dF = None
# dataframe init
with Timer.Timer("init"):
flows = pd.DataFrame(None, columns = flowKeys+["flowValue"]).set_index(flowKeys)
dNDF = pd.DataFrame(None, columns = flowKeys+columns.tolist()).set_index(flowKeys)
# lending flow
with Timer.Timer("add1"):
flows.loc[("CAP", date1),"flowValue"] = -1
with Timer.Timer("add2"):
dNDF.loc[("CAP", date1),:] = 0
# reimbursement of the capital flow
with Timer.Timer("add3"):
flows.loc[("CAP", date2),"flowValue"] = 1
with Timer.Timer("add4"):
dNDF.loc[("CAP", date2),:] = 0
# interest flow
with Timer.Timer("add5"):
flows.loc[("INT", date2),"flowValue"] = rate * (date2 - date1).days/360
with Timer.Timer("add6"):
dNDF.loc[("INT", date2),:]= 0
При регистрации производительности я получаю следующие результаты: инициализация 2 пустых кадров данных занимает 10 мс и приблизительно добавить одну строку в вышеупомянутом кадре данных.
[set]
Elapsed: 0.326904296875
[init]
Elapsed: 11.828125
[add1]
Elapsed: 3.95703125
[add2]
Elapsed: 10.489013671875
[add3]
Elapsed: 2.76513671875
[add4]
Elapsed: 9.325927734375
[add5]
Elapsed: 3.031005859375
[add6]
Elapsed: 10.52294921875
[test]
Elapsed: 52.6328125
Есть ли способ радикально улучшить скорость этого кода? Можно воспроизвести проблему, скопировав / вставив код, но модуль таймера, как показано ниже, контролирует время выполнения в мс:
import time
class Timer(object):
def __init__(self, name=None):
self.name = name
def __enter__(self):
self.tstart = time.time()
def __exit__(self, type, value, traceback):
if self.name:
print('[%s]' % self.name,)
print('Elapsed: %s' % (1000*time.time() - 1000*self.tstart))