Создание меток и обновление столбца на основе нескольких условий

#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 — любой пользователь с сеансом = 0
  • frequent_visitor — любой пользователь с сеансом gt; 0 и count_session_products gt;gt; 0
  • first_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.