Ускорьте выполнение вложенных циклов для фрейма данных

#python #python-3.x #pandas #dataframe #for-loop

Вопрос:

У меня есть df под названием «Серия», состоящий из более чем 2600 строк и 120 столбцов. Вот выдержка:

          Date  Gasoil  Gasoline     Oil     Gas
0  2010-12-31  100.00    100.00  100.00  100.00
1  2011-01-03  103.97     99.88  100.18  105.55
2  2011-01-04  100.85     99.33   97.81  106.00
3  2011-01-05  102.02    100.61   98.82  101.54
 

Я создал несколько пустых фреймов данных с теми же именами столбцов и индексом, что и «Серия». Каждая из этих копий DF должна содержать какую-либо функцию в исходной серии df (скользящие средние, скользящие процентили и т. Д.).

Например, один из таких кадров данных копирования называется «log_returns». В каждой ячейке log_returns мне нужно рассчитать логарифмические возвраты на основе соответствующего столбца фрейма данных «Серия».

Это тот результат, который я имею в виду. Например, журнал возврата газойля за 2011-01-03 = журнал (103,97/100).

          Date  Gasoil Gasoline     Oil     Gas
0  2010-12-31                                 
1  2011-01-03   3.89%   -0.12%   0.18%   5.40%
2  2011-01-04  -3.05%   -0.55%  -2.39%   0.43%
3  2011-01-05   1.15%    1.28%   1.03%  -4.30%
 

Для этого я написал вложенный цикл for:

 rows_list = list(range(1, len(log_returns)))
columns_list = list(range(0, len(log_returns.columns)))

for row in rows_list:
    for column in columns_list:
        log_returns.iloc[row,column] = np.log(Series.iloc[row,column] / Series.iloc[row-1,column])

 

К сожалению, код запускается очень медленно. Существуют ли более быстрые альтернативы?
Спасибо

Ответ №1:

После установки даты в качестве индекса результат можно получить с помощью однострочного:

 df = pd.DataFrame.from_records(
[(pd.to_datetime('2010-12-31'),  100.00,    100.00,  100.00,  100.00),
(pd.to_datetime('2011-01-03'),  103.97,     99.88,  100.18,  105.55),
(pd.to_datetime('2011-01-04'),  100.85,     99.33,   97.81,  106.00),
(pd.to_datetime('2011-01-05'),  102.02,    100.61,   98.82,  101.54)],
columns = ['Date',  'Gasoil',  'Gasoline',     'Oil',     'Gas'])
df = df.set_index('Date')
#this is the one-liner
np.log(df/df.shift(1))*100
 

Ответ №2:

Попробуй:

 df.loc[:, "Gasoil":] = (
    np.log(df.loc[:, "Gasoil":] / df.loc[:, "Gasoil":].shift(-1)).shift() * -100
).fillna("")
print(df)
 

С принтами:

          Date    Gasoil  Gasoline       Oil       Gas
0  2010-12-31                                        
1  2011-01-03  3.893221 -0.120072  0.179838  5.401459
2  2011-01-04 -3.046813 -0.552183 -2.394175  0.425432
3  2011-01-05  1.153461  1.280402  1.027319 -4.298628