загружает данные из CSV в панда и сделать проверку на некоторых из таких областей, как это:Повышение эффективности проверки данных в пандах
(1.5s) loans['net_mortgage_margin'] = loans['net_mortgage_margin'].map(lambda x: convert_to_decimal(x))
(1.5s) loans['current_interest_rate'] = loans['current_interest_rate'].map(lambda x: convert_to_decimal(x))
(1.5s) loans['net_maximum_interest_rate'] = loans['net_maximum_interest_rate'].map(lambda x: convert_to_decimal(x))
(48s) loans['credit_score'] = loans.apply(lambda row: get_minimum_score(row), axis=1)
(< 1s) loans['loan_age'] = ((loans['factor_date'] - loans['first_payment_date'])/np.timedelta64(+1, 'M')).round() + 1
(< 1s) loans['months_to_roll'] = ((loans['next_rate_change_date'] - loans['factor_date'])/np.timedelta64(+1, 'M')).round() + 1
(34s) loans['first_payment_change_date'] = loans.apply(lambda x: validate_date(x, 'first_payment_change_date', loans.columns), axis=1)
(37s) loans['first_rate_change_date'] = loans.apply(lambda x: validate_date(x, 'first_rate_change_date', loans.columns), axis=1)
(39s) loans['first_payment_date'] = loans.apply(lambda x: validate_date(x, 'first_payment_date', loans.columns), axis=1)
(39s) loans['maturity_date'] = loans.apply(lambda x: validate_date(x, 'maturity_date', loans.columns), axis=1)
(37s) loans['next_rate_change_date'] = loans.apply(lambda x: validate_date(x, 'next_rate_change_date', loans.columns), axis=1)
(36s) loans['first_PI_date'] = loans.apply(lambda x: validate_date(x, 'first_PI_date', loans.columns), axis=1)
(36s) loans['servicer_name'] = loans.apply(lambda row: row['servicer_name'][:40].upper().strip(), axis=1)
(38s) loans['state_name'] = loans.apply(lambda row: str(us.states.lookup(row['state_code'])), axis=1)
(33s) loans['occupancy_status'] = loans.apply(lambda row: get_occupancy_type(row), axis=1)
(37s) loans['original_interest_rate_range'] = loans.apply(lambda row: get_interest_rate_range(row, 'original'), axis=1)
(36s) loans['current_interest_rate_range'] = loans.apply(lambda row: get_interest_rate_range(row, 'current'), axis=1)
(33s) loans['valid_credit_score'] = loans.apply(lambda row: validate_credit_score(row), axis=1)
(60s) loans['origination_year'] = loans['first_payment_date'].map(lambda x: x.year if x.month > 2 else x.year - 1)
(< 1s) loans['number_of_units'] = loans['unit_count'].map(lambda x: '1' if x == 1 else '2-4')
(32s) loans['property_type'] = loans.apply(lambda row: validate_property_type(row), axis=1)
Большинства из них являются функций, которые находят значение row
, несколько прямого преобразование элемент для чего-то другого, но в целом, они выполняются для всей строки данных по строкам. Когда этот код был написан, кадры данных были достаточно малы, чтобы это не было проблемой. Однако код теперь адаптирован для принятия значительно больших таблиц, так что эта часть кода занимает слишком много времени.
Что такое лучший способ оптимизировать это? Моя первая мысль заключалась в том, чтобы идти по строкам, но применять все эти функции/преобразования в строке один раз (т. Е. Для строки в df, do func1, func2, ..., func21), но я не уверен, что это лучший способ справиться с этим. Есть ли способ избежать лямбда получить тот же результат, например, так как я предполагаю, что это лямбда, которая занимает много времени? Запуск Python 2.7 в случае, если это имеет значение.
Редактирование: большинство из этих вызовов работают примерно с той же скоростью за строку (несколько довольно быстрые). Это dataframe с 277 659 строк, который находится в 80-м процентиле по размеру.
Edit2: пример функции:
def validate_date(row, date_type, cols):
date_element = row[date_type]
if date_type not in cols:
return np.nan
if pd.isnull(date_element) or len(str(date_element).strip()) < 2: # can be blank, NaN, or "0"
return np.nan
if date_element.day == 1:
return date_element
else:
next_month = date_element + relativedelta(months=1)
return pd.to_datetime(dt.date(next_month.year, next_month.month, 1))
Это похоже на самый длинный вызов (origination_year), который извлекает значения из даты объекта (год, месяц и т.д.). Другие, например property_type, просто проверяют нерегулярные значения (например, «N/A», «NULL» и т. Д.), Но все-таки занимают немного времени, чтобы пройти через каждый.
Если у вас уже есть функция 'convert_to_decimal', это просто беспорядок для записи' lambda x: convert_to_decimal (x) '. Это то же самое, что писать lambda y: (lambda x: convert_to_decimal (x)) (y) ' –
Вопрос 1: ** что ** медленное? У вас есть 4-5 функций, которые мы не видим в коде, некоторые, например, 'convert_to_decimal'. Я надеюсь, что это быстро, другие, например' validate_date', где вы передаете ему столбец * может * быть проблемами, но мы может только предполагать. По крайней мере, было бы полезно посыпать некоторые вызовы 'print (time.time())'. –
Отредактировано со временем за звонок. Дело не в том, что какой-то конкретный вызов медленный; это то, что в целом они добавляют больше времени, чем идеально, и по крайней мере кажется, что не называть каждую строку снова и снова, но я не знаю, заменит ли это 8,5 минут 7,6 минутами. – user2524282