Итак, если ваша единственная проблема с методом 2 заключается в том, что вы не хотите смотреть на глобальный df2, почему бы не передать его в качестве второго параметра вашей функции?Например.
def _reduce(df_orderitems, df_): ...
Но я бы не советовал делать точно ни один из описанных здесь методов.
Итерирование по фрейму данных, как в методе 1, никогда не будет таким быстрымиспользуя apply
, потому что apply
внутренне оптимизирован с использованием Cython.На самом деле, это будет очень медленно (как вы нашли). Здесь - хорошее объяснение того, почему и ваши варианты для ускорения операций.
Ваш вопрос немного расплывчат, почему иначе вам не нравится метод 2, но я бы хотелсделать две вещи, если бы я был на вашем месте.
- Я бы использовал SQL-подобные операции в пандах для объединения двух фреймов данных.
У вас есть перекрывающиеся столбцы ('store_id' и 'product_id'), которые появляются как в df1, так и в df2, так что я бы сделал в пандах SQL-стиль join
, чтобы объединить два кадра данных.Таким образом, вам не придется иметь дело с битами индексации, которые вы сейчас делаете.
Давайте сначала создадим фиктивные данные, которые, я думаю, представляют вашу ситуацию:
df1 = pd.DataFrame({"store_id": ['A','A','A','B','B'],
"product_id": [0, 1, 2, 1, 0],
"record_number": [0, 1, 2, 3, 4],
"data": [21, 22, 28, 26, 25]})
df2 = pd.DataFrame({"store_id":['A','A','A','B','B', 'B'],
"product_id": [0, 1, 2, 0, 1, 2],
"more_data":[35, 39, 36, 33, 37, 32]})
Затем вы можете использовать функцию join
для объединения двух фреймов данных в стиле SQL на перекрывающихся друг с другомстолбцы (join
использует индексы кадра данных).Это отображает данные из df2 на данные в df1, чтобы создать новый объединенный фрейм данных.( Подробно описано в pandas docs )
merged = df1.join(df2.set_index(['store_id','product_id']),
how='left',
on=['store_id','product_id'],
rsuffix='_df2_data')
Что дает вам
store_id product_id record_number product_data more_product_data
0 A 0 0 21 35
1 A 1 1 22 39
2 A 2 2 28 36
3 B 1 3 26 37
4 B 0 4 25 33
В зависимости от полноты данных, вы, вероятно, захотите проверить наличие NaN
Вы также можете фильтровать, преобразовывать и т. Д. Ваши данные по мере необходимости (если есть другие этапы на этапе обработки)
Тогда я бы использовал
apply
(
progress_apply
), чтобы выполнить шаг прогнозирования
Вы можете либо создать новую функцию, либо использовать лямбда-функцию, в зависимости от вашей ситуации
def train_predict(a, b):
return a + b
def predict_outcome(df_row):
return train_predict(df_row[['product_data']].values[0],
df_row[['more_product_data']].values[0])
tqdm.pandas(desc='predict the outcome')
merged['prediction'] = merged.progress_apply(lambda x: train_predict(x['product_data'],x['more_product_data']),
axis='columns')
# or
tqdm.pandas(desc='predict the outcome')
merged['prediction'] = merged.progress_apply(predict_outcome, axis='columns')
(аргумент axis='columns'
указывает apply
перебирать строки df)