Я обрабатываю фрейм данных с потоком кликов и извлекаю функции для каждого пользователя в потоке кликов, которые будут использоваться в проекте машинного обучения.
Фрейм данных выглядит примерно так:
data = pd.DataFrame({'id':['A01','B01','A01','C01','A01','B01','A01'],
'event':['search','search','buy','home','cancel','home','search'],
'date':['2018-01-01','2018-01-01','2018-01-02','2018-01-03','2018-01-04','2018-01-04','2018-01-06'],
'product':['tablet','dvd','tablet','tablet','tablet','book','book'],
'price': [103,2,203,103,203,21,21]})
data['date'] = pd.to_datetime(data['date'])
Так как я должен создавать функции для каждого пользователя, я использую групповую настройку / применение с пользовательской функцией, такой как:
featurized = data.groupby('id').apply(featurize)
Создание пользовательских функций займет часть информационного кадра и создаст много (сотни) функций. Весь процесс слишком медленный, поэтому я ищу рекомендацию, чтобы сделать это более эффективно.
Пример функции, используемой для создания объектов:
def featurize(group):
features = dict()
# Userid
features['id'] = group['id'].max()
# Feature 1: Number of search events
features['number_of_search_events'] = (group['event']=='search').sum()
# Feature 2: Number of tablets
features['number_of_tablets'] = (group['product']=='tablet').sum()
# Feature 3: Total time
features['total_time'] = (group['date'].max() - group['date'].min()) / np.timedelta64(1,'D')
# Feature 4: Total number of events
features['events'] = len(group)
# Histogram of products examined
product_counts = group['product'].value_counts()
# Feature 5 max events for a product
features['max_product_events'] = product_counts.max()
# Feature 6 min events for a product
features['min_product_events'] = product_counts.min()
# Feature 7 avg events for a product
features['mean_product_events'] = product_counts.mean()
# Feature 8 std events for a product
features['std_product_events'] = product_counts.std()
# Feature 9 total price for tablet products
features['tablet_price_sum'] = group.loc[group['product']=='tablet','price'].sum()
# Feature 10 max price for tablet products
features['tablet_price_max'] = group.loc[group['product']=='tablet','price'].max()
# Feature 11 min price for tablet products
features['tablet_price_min'] = group.loc[group['product']=='tablet','price'].min()
# Feature 12 mean price for tablet products
features['tablet_price_mean'] = group.loc[group['product']=='tablet','price'].mean()
# Feature 13 std price for tablet products
features['tablet_price_std'] = group.loc[group['product']=='tablet','price'].std()
return pd.Series(features)
Одна потенциальная проблема заключается в том, что каждая функция потенциально сканирует весь блок, поэтому, если у меня есть 100 функций, я сканирую блок 100 раз вместо одного.
Например, функция может быть числом «планшетных» событий, которые есть у пользователя, другая может быть числом «домашних» событий, другая может быть средней разницей во времени между «поисковыми» событиями, а затем средней разницей во времени между » поиск "событий" для "планшетов" и т. д. и т. д. Каждая функция может быть закодирована как функция, которая берет фрагмент (df) и создает функцию, но когда у нас есть сотни функций, каждая из них сканирует весь фрагмент, когда достаточно одного линейного сканирования , Проблема в том, что код станет уродливым, если я сделаю руководство для цикла над каждой записью в чанке и закодирую все функции в цикле.
Вопросы:
Если мне придется обрабатывать фрейм данных сотни раз, есть ли способ абстрагировать это за одно сканирование, которое создаст все необходимые функции?
Есть ли улучшение скорости по сравнению с подходом группового режима / применения, который я сейчас использую?