Проблемы производительности python при использовании циклов с большими таблицами

Я использую python и несколько библиотек, таких как pandas и scipy, для подготовки данных, чтобы я мог начать более глубокий анализ. Для подготовки я, например, создаю новые столбцы с разницей в две даты.
Мой код дает ожидаемые результаты, но он очень медленный, поэтому я не могу использовать его для таблицы с 80-тысячными строками. Время выполнения займет около 80 минут на стол только для этой простой операции.

Проблема определенно связана с моей операцией записи:

tableContent[6]['p_test_Duration'].iloc[x] = difference


Кроме того, python выдает предупреждение:

полный пример кода для разницы дат:

import time
from datetime import date, datetime

tableContent[6]['p_test_Duration'] = 0

#for x in range (0,len(tableContent[6]['p_test_Duration'])):
for x in range (0,1000):
    p_test_ZEIT_ANFANG = datetime.strptime(tableContent[6]['p_test_ZEIT_ANFANG'].iloc[x], '%Y-%m-%d %H:%M:%S')
    p_test_ZEIT_ENDE = datetime.strptime(tableContent[6]['p_test_ZEIT_ENDE'].iloc[x], '%Y-%m-%d %H:%M:%S')
    difference = p_test_ZEIT_ENDE - p_test_ZEIT_ANFANG

    tableContent[6]['p_test_Duration'].iloc[x] = difference

правильная таблица результатов:

3 ответа

Решение

Уберите цикл и примените функции ко всей серии.

ZEIT_ANFANG = tableContent[6]['p_test_ZEIT_ANFANG'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S'))
ZEIT_ENDE = tableContent[6]['p_test_ZEIT_ENDE'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S'))
tableContent[6]['p_test_Duration'] = ZEIT_ENDE - ZEIT_ANFANG

Вы можете векторизовать преобразование дат, используя pd.to_datetime и избегать использования apply без необходимости.

tableContent[6]['p_test_Duration'] = (
    pd.to_datetime(tableContent[6]['p_test_ZEIT_ENDE']) -
    pd.to_datetime(tableContent[6]['p_test_ZEIT_ANFANG'])
)

Кроме того, вы получали SettingWithCopy предупреждение из-за цепочки индексации

tableContent[6]['p_test_Duration'].iloc[x] = difference

Что вам не нужно беспокоиться, если вы поступите так, как я предложил.

Другие ответы хороши, но я бы порекомендовал вам вообще избегать цепной индексации. Документы pandas явно не рекомендуют цепную индексацию, поскольку она либо дает ненадежные результаты, либо медленна (из-за многочисленных обращений к __getitem__). Предполагая, что ваш фрейм данных многоиндексирован, вы можете заменить:

tableContent[6]['p_test_Duration'].iloc[x] = difference

с:

tableContent.loc[x, (6, 'p_test_Duration')] = difference

Иногда вы можете обойти эту проблему, но почему бы не изучить метод с наименьшей вероятностью вызвать проблемы в будущем?

Другие вопросы по тегам