Ускорить панды блок - PullRequest
       7

Ускорить панды блок

0 голосов
/ 02 октября 2019

Я мог бы использовать некоторую помощь для ускорения этого блока кода. Я предполагаю, что именно конкат-операции замедляют код, но я не уверен. Этот цикл занимает в 20 раз больше времени для выполнения оставшейся части кода в моей функции.

df = pd.DataFrame()
for index, row in p_data_df.iterrows():
    test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
    if 'S' not in test_df.columns:
        test_df.insert(0, 'S', row.loc['S'])
        test_df.insert(1, 'C #', row.loc['C #'])
        test_df.insert(2, 'Num', row.loc['Num'])

    df = pd.concat([df, test_df], axis=0)

Ответы [ 2 ]

2 голосов
/ 02 октября 2019

Никогда не вызывайте pd.concat внутри цикла for. Это приводит к квадратичному копированию: concat возвращает новый DataFrame. Для нового DataFrame должно быть выделено место, а данные из старых DataFrames должны быть скопированы в новый DataFrame.

Таким образом, если ваш фрейм данных имеет N строк, вам потребуется O (N ^ 2) копий. для завершения цикла.

Используйте список словарей или список списков вместо фрейма данных для накопления результатов, а за пределами цикла for создайте свой фрейм данных со списком результатов. Таким образом, вы сэкономите много времени на выполнение, панды для этого не сделано.

Вот как вы можете это сделать:

list_res = []
for index, row in p_data_df.iterrows():
    test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
    if 'S' not in test_df.columns:
        test_df.insert(0, 'S', row.loc['S'])
        test_df.insert(1, 'C #', row.loc['C #'])
        test_df.insert(2, 'Num', row.loc['Num'])
    list_res.append(test_df)

df = pd.concat(list_res, axis=0)

Дополнительные советы по ускорению вашего кода

iterrows - самый медленный из возможных способов итерациифрейм данных, поскольку каждая строка должна быть преобразована в серию. Если вы используете itertuples , этого не произойдет. Вы можете использовать itertuples, не слишком меняя код, но увеличивая производительность.

Существуют другие методы (векторизация, функция применения, Cython ...), которые потребуют немного более широкой модификации вашего кода, но позволят вам иметь более эффективный код. Я оставляю вам эту ссылку для получения дополнительной информации.

1 голос
/ 02 октября 2019

При использовании concat получается квадратичная копия. Каждый раз, когда вы добавляете строку, эта операция возвращает копию предыдущего кадра данных и новую строку. Лучше всего сохранить список всех строк, а затем выполнить только одну окончательную конкатенацию в конце.

df = []
for index, row in p_data_df.iterrows():
    test_df = log_df.loc[row['Mid-C']].to_frame().transpose()
    if 'S' not in test_df.columns:
        test_df.insert(0, 'S', row.loc['S'])
        test_df.insert(1, 'C #', row.loc['C #'])
        test_df.insert(2, 'Num', row.loc['Num'])
    df.append(test_df)
df = pd.concat(df, axis=0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...