#python #pandas #dataframe #conditional-statements #data-analysis
Вопрос:
У меня есть фрейм данных, который выглядит следующим образом:
data = { 'user_id': [ '9EPWZVMNP6D6KWX', '9EPWZVMNP6D6KWX', '9EPWZVMNP6D6KWX', '9EPWZVMNP6D6KWX', '9EPWZVMNP6D6KWX', '9EPWZVMNP6D6KWX' ], 'timestamp': [ 1612139269, 1612139665, 1612139579, 1612141096, 1612143046, 1612143729 ], 'type': [ 'productDetails', 'productDetails', 'checkout:confirmation', 'checkout:confirmation', 'productList', 'checkout:confirmation' ], 'session': [0,1,2,3,4,5], 'count_session_products': [4, 1, 0, 4, 2, 2], 'loyalty' : [0,0,0,0,0,0] } test_df = pd.DataFrame(data) test_df
идентификатор пользователя | отметка времени | Тип | сессия | подталкивает | лояльность |
---|---|---|---|---|---|
9EPWZVMNP6D6KWX | 1612139269 | Сведения о продукте | 0 | 4 | 0 |
9EPWZVMNP6D6KWX | 1612139665 | Сведения о продукте | 1 | 1 | 0 |
9EPWZVMNP6D6KWX | 1612139579 | оформление заказа:подтверждение | 2 | 0 | 0 |
9EPWZVMNP6D6KWX | 1612141096 | оформление заказа:подтверждение | 3 | 4 | 0 |
9EPWZVMNP6D6KWX | 1612143046 | Список товаров | 4 | 2 | 0 |
9EPWZVMNP6D6KWX | 1612143729 | оформление заказа:подтверждение | 5 | 2 | 0 |
Теперь я хочу создать ярлыки лояльности и их условия, такие как:
first_time_visitor
— любой пользователь с сеансом = 0frequent_visitor
— любой пользователь с сеансом gt; 0 и count_session_products gt;gt; 0first_time_customer
— при первом оформлении заказа:подтверждение отображается в столбце типrepeat_customer
— второй раз при оформлении заказа:подтверждение отображается в столбце типloyal_customer
— третий раз оформления заказа:подтверждение отображается в столбце тип
У меня уже есть условия для first_time_visitor
и frequent_visitor
, но у меня возникают проблемы с созданием first_time_customer
repeat_customer
и loyal_customer
ярлыков.
Условия для first_time_visitor
и frequent_visitor
являются следующими:
test_df['loyalty'] = np.where((test_df['session'] gt; 0) amp; ((test_df['type'] != 'checkout:confirmation')), 'frequent_visitor', None) test_df.loc[test_df['session'] == 0, 'loyalty'] = 'first_time_visitor'
что дает мне фрейм данных, выглядящий примерно так:
идентификатор пользователя | отметка времени | Тип | сессия | подталкивает | лояльность |
---|---|---|---|---|---|
9EPWZVMNP6D6KWX | 1612139269 | Сведения о продукте | 0 | 4 | first_time_visitor |
9EPWZVMNP6D6KWX | 1612139665 | Сведения о продукте | 1 | 1 | частый посетитель |
9EPWZVMNP6D6KWX | 1612139579 | оформление заказа:подтверждение | 2 | 0 | 0 |
9EPWZVMNP6D6KWX | 1612141096 | оформление заказа:подтверждение | 3 | 4 | 0 |
9EPWZVMNP6D6KWX | 1612143046 | Список товаров | 4 | 2 | частый посетитель |
9EPWZVMNP6D6KWX | 1612143729 | оформление заказа:подтверждение | 5 | 2 | 0 |
У меня было только несколько идей, одна из которых заключалась в том, чтобы использовать first_valid_index()
или argmax()
найти индекс и каким-то образом использовать его в состоянии для создания first_time_customer
метки. Но я не уверен, как выполнить эти условия.
(test_df.type.values == 'checkout:confirmation').argmax() test_df[test_df.type == 'checkout:confirmation'].first_valid_index()
В конце концов, я ожидал бы, что моя колонка лояльности будет выглядеть так:
идентификатор пользователя | отметка времени | Тип | сессия | подталкивает | лояльность |
---|---|---|---|---|---|
9EPWZVMNP6D6KWX | 1612139269 | Сведения о продукте | 0 | 4 | first_time_visitor |
9EPWZVMNP6D6KWX | 1612139665 | Сведения о продукте | 1 | 1 | частый посетитель |
9EPWZVMNP6D6KWX | 1612139579 | оформление заказа:подтверждение | 2 | 0 | first_time_customer |
9EPWZVMNP6D6KWX | 1612141096 | оформление заказа:подтверждение | 3 | 4 | repeat_customer |
9EPWZVMNP6D6KWX | 1612143046 | Список товаров | 4 | 2 | частый посетитель |
9EPWZVMNP6D6KWX | 1612143729 | оформление заказа:подтверждение | 5 | 2 | лояльный клиент |
Любые предложения и помощь будут оценены по достоинству. Спасибо!
Комментарии:
1. Это для живого приложения / являются ли данные живыми? Или у вас есть какой-то старый набор данных, и вы пытаетесь обновить, когда пользователь приобрел ту или иную лояльность? Если это для какого-то живого приложения, может быть проще обновить лояльность для пользователя в отдельной таблице при изменении лояльности, а не таким образом. Тем не менее, это, безусловно, все еще можно сделать.
2. Можете ли вы дать некоторые предложения/примеры того, как это можно было бы сделать? Потому что я застрял. И сейчас это всего лишь базовый анализ, позже он будет использоваться на реальных данных.
3. будет во многом зависеть от приложения и модели и многого другого. и я подумал, что если вы разрабатываете все приложение и контролируете все с его помощью, а не получаете живые данные откуда-то еще. затем, когда человек совершает покупку, вы можете посмотреть, каков уровень его лояльности там, где вы его сохранили, и просто увеличить его и сохранить новую лояльность. затем всякий раз, когда у вас есть покупка, вы не просматриваете всю таблицу, подсчитывая покупки, а просто сравниваете их с самым последним уровнем лояльности.
Ответ №1:
Одним из способов сделать это было бы:
mask = test_df.type.eq('checkout:confirmation') mask = mask amp; mask.cumsum().le(3) test_df.loc[mask, 'loyalty'] = ( ['first_time_customer', 'repeat_customer', 'loyal_customer'][:mask.sum()] )
Ответ №2:
правка: в моем первоначальном посте был первый цикл n
в обратном порядке, я не думаю, что нам это нужно или это помогает… я также обновил его, чтобы мы не учитывали предыдущие случаи оформления заказа:подтверждение, но вместо этого просто добавьте 1 к последнему счету оформления заказа:подтверждение, чтобы мы могли пропустить столько строк.
Я думаю, что мне удалось получить решение, которое использует двойной обратный цикл над фреймом данных. Наверное, не самая эффективная вещь в мире, но должна работать…
Он использует идею о том, что каждая проверка, похоже, поднимает пользователя на уровень, поэтому мы используем целые числа и просто добавляем 1 к лояльности, прежде чем сопоставить эти целые числа со словами. Поскольку уровень лояльности = 3 является самым высоким, мы можем выйти из цикла раньше, если достигнем этого уровня 3.
Это никак не влияет на статус посетителя, поэтому вы захотите убедиться, что ваши два метода работают совместно для этого.
df['l'] = 0 # makes a new temp column in the df to store our loyalty calcs for n in range(len(df)): # start to loop through the dataframe l = 0 # set the loyalty level to 0 if df['type'][n] == 'checkout:confirmation': # only do this for checkouts l = 1 # if it is a checkout, the loyalty is now 1 (might go up) for i in reversed(range(n)): # start looking at the rows above the current one for more checkouts if df['user_id'][n] == df['user_id'][i] and df['type'][i] == 'checkout:confirmation': # make sure the userid matches as well as the above row is checkout l = min(df['l'][i] 1,3) # if our new loyalty would be gt; 3, just set it to 3, which is the max break df['l'][n] = l # set the loyalty level in row n to l df['loyalty'] = df['l'].map({1:'first_time_customer',2:'frequent_customer',3:'loyal_customer'}) # maps the integers to text for the loyalty. gives NaN for the non-purchase rows.