Advertisement
Kelevra_Slevin

Когортный анализ

May 18th, 2023 (edited)
1,813
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.12 KB | None | 0 0
  1. #Тема 2. Когортный анализ
  2. #1  Урок 3. Профиль пользователя. Функции first() и last()
  3. #Чтобы проще было делить клиентов на когорты, лучше заранее составить их профили — таблицу с деталями первого посещения каждого пользователя, такими как источник перехода на сайт, страна, устройство.
  4.  
  5. #Для этого вам предстоит:
  6.  
  7. #изучить две новые функции,
  8. #написать собственную.
  9. #1.1  Функции first() и last()
  10. #В создании профилей вам помогут агрегирующие функции first() и last(). Первая возвращает первое значение в группе, вторая — последнее.
  11.  
  12. #Для примера загрузим и откроем данные о выпуске по годам и платформам трёх популярных видеоигр — Monopoly, SimCity 2000 и Terraria. #Задача: посмотреть, в каком году и на какой платформе впервые вышла каждая игра.
  13.  
  14. import pandas as pd
  15. games = pd.read_csv('/datasets/three_games.csv')
  16. games
  17. name    platform    year_of_release
  18. 0   Monopoly    PC  1994-01-01
  19. 1   SimCity 2000    PC  1992-01-01
  20. 2   Monopoly    Wii 2008-01-01
  21. 3   Monopoly    PS  1997-01-01
  22. 4   SimCity 2000    PS  1996-01-01
  23. 5   Terraria    X360    2013-01-01
  24. 6   Monopoly    X360    2008-01-01
  25. 7   SimCity 2000    SNES    1995-01-01
  26. 8   Monopoly    PS2 2008-01-01
  27. 9   Terraria    PS3 2013-01-01
  28. 10  Monopoly    PS3 2008-01-01
  29. 11  SimCity 2000    SAT 1994-01-01
  30. 12  Monopoly    DS  2010-01-01
  31. 13  Monopoly    N64 1999-01-01
  32. 14  Terraria    PC  2011-01-01
  33. 15  SimCity 2000    GBA 2003-01-01
  34. 16  Terraria    PSV 2013-01-01
  35. 17  Terraria    3DS 2016-01-01
  36. 18  Terraria    PS4 2014-01-01
  37. 19  Terraria    XOne    2014-01-01
  38. 20  Terraria    WiiU    2016-01-01
  39. #Самый ранний год выхода каждой игры получить несложно — достаточно сгруппировать данные по столбцу 'name' и применить функцию min() к значениям 'year_of_release':
  40.  
  41. games.groupby('name').agg({'year_of_release': 'min'})
  42. year_of_release
  43. name   
  44. Monopoly    1994-01-01
  45. SimCity 2000    1992-01-01
  46. Terraria    2011-01-01
  47. #Другое дело — платформы, на которых впервые вышли игры.
  48.  
  49. #Способ с min() не годится — результатом будут «наименьшие» строки. Чтобы найти платформы, на которых впервые вышла каждая игра, применим функцию first(). При группировке она возвращает не минимальное, а первое значение в каждой группе, поэтому важно заранее отсортировать данные по названию и году выпуска:
  50.  
  51. games = games.sort_values(by=['name', 'year_of_release'])
  52. games
  53. name    platform    year_of_release
  54. 0   Monopoly    PC  1994-01-01
  55. 3   Monopoly    PS  1997-01-01
  56. 13  Monopoly    N64 1999-01-01
  57. 2   Monopoly    Wii 2008-01-01
  58. 6   Monopoly    X360    2008-01-01
  59. 8   Monopoly    PS2 2008-01-01
  60. 10  Monopoly    PS3 2008-01-01
  61. 12  Monopoly    DS  2010-01-01
  62. 1   SimCity 2000    PC  1992-01-01
  63. 11  SimCity 2000    SAT 1994-01-01
  64. 7   SimCity 2000    SNES    1995-01-01
  65. 4   SimCity 2000    PS  1996-01-01
  66. 15  SimCity 2000    GBA 2003-01-01
  67. 14  Terraria    PC  2011-01-01
  68. 5   Terraria    X360    2013-01-01
  69. 9   Terraria    PS3 2013-01-01
  70. 16  Terraria    PSV 2013-01-01
  71. 18  Terraria    PS4 2014-01-01
  72. 19  Terraria    XOne    2014-01-01
  73. 17  Terraria    3DS 2016-01-01
  74. 20  Terraria    WiiU    2016-01-01
  75. #Добавляем first(), чтобы узнать первое значение 'platform' в каждой группе. Благодаря сортировке оно совпадает со значением, соответствующим самой ранней дате:
  76.  
  77. games.groupby('name').agg({'year_of_release': 'min', 'platform': 'first'})
  78. year_of_release platform
  79. name       
  80. Monopoly    1994-01-01  PC
  81. SimCity 2000    1992-01-01  PC
  82. Terraria    2011-01-01  PC
  83. #Функция min() определила год первого выхода каждой игры, а first() — соответствующую этому году платформу.
  84.  
  85. #У функции min() есть зеркальная функция max(), которая возвращает не минимальное, а максимальное значение. Такая же «сводная сестра» функции first() — функция last(). При группировке last() возвращает последнее значение в каждой группе:
  86.  
  87. games.groupby('name').agg(
  88.     {'year_of_release': ['min', 'max'], 'platform': ['first', 'last']}
  89. )
  90. year_of_release platform
  91. min max first   last
  92. name               
  93. Monopoly    1994-01-01  2010-01-01  PC  DS
  94. SimCity 2000    1992-01-01  2003-01-01  PC  GBA
  95. Terraria    2011-01-01  2016-01-01  PC  WiiU
  96. #1.2  Типичный набор данных пользователя
  97. #Все системы бизнес-аналитики собирают примерно один и тот же минимальный набор информации о пользователях. Есть две большие группы данных: журнал посещений сайта пользователями, то есть пользовательских сессий, и журнал покупок.
  98.  
  99. #1.2.0.1  Данные журнала пользовательских сессий
  100. #уникальный идентификатор пользователя;
  101. #дата начала сессии;
  102. #дата окончания или длительность сессии;
  103. #устройство, с которого пользователь заходил на сайт;
  104. #географическое положение в момент посещения сайта.
  105. #1.2.0.2  Данные журнала покупок
  106. #уникальный идентификатор пользователя,
  107. #дата совершения покупки,
  108. #сумма покупки.
  109. #Профили пользователей составляют в три этапа:
  110.  
  111. #Загрузить данные журнала посещений.
  112. #Для каждого пользователя определить дату и время первой сессии.
  113. #Для каждого пользователя определить соответствующие задаче параметры первой сессии. Например, источник перехода на сайт.
  114. #Возьмём датасет с данными пользовательских сессий международного интернет-магазина электронных книг «Читать не вредно»:
  115.  
  116. sessions = pd.read_csv('/datasets/sessions.csv')
  117. sessions['session_start'] = pd.to_datetime(sessions['session_start'])
  118. session
  119. user_id region  device  channel session_duration    session_start
  120. 0   94834909438 Germany iPhone  Yandex  5.417238    2019-05-01 12:59:48
  121. 1   142292250445    United States   iPhone  Organic 33.232475   2019-05-01 21:25:00
  122. 2   486879489291    United States   Mac Organic 33.635569   2019-05-01 21:18:40
  123. 3   996478278264    Germany iPhone  Yandex  76.792801   2019-05-01 07:37:52
  124. 4   857023407503    United States   Android Organic 5.976421    2019-05-01 01:35:01
  125. ... ... ... ... ... ... ...
  126. 282932  507281681954    United States   PC  Organic 6.316422    2019-05-14 06:35:22
  127. 282933  584727896171    France  PC  Organic 51.814506   2019-05-14 18:23:01
  128. 282934  200769562990    United States   Android Organic 15.380831   2019-05-14 16:20:10
  129. 282935  569449250064    Germany iPhone  Organic 24.139972   2019-05-14 09:15:01
  130. 282936  477066637255    United States   Android Yandex  10.855441   2019-05-14 09:01:11
  131. 282937 rows × 6 columns
  132.  
  133. #Содержание столбцов:
  134.  
  135. #user_id — уникальный идентификатор пользователя;
  136. #region — географический регион, из которого пользователь зашёл на сайт;
  137. #device — устройство, которым воспользовался посетитель;
  138. #channel — рекламный канал, из которого пользователь перешёл на сайт;
  139. #session_duration — длительность сессии;
  140. #session_start — дата и время начала сессии.
  141. #Для создания пользовательских профилей с датой первого посещения и источником перехода на сайт напишем функцию get_profiles(). В ней сгруппируем значения датафрейма по пользовательскому ID и применим функцию first():
  142.  
  143. def get_profiles(sessions):
  144.     # сортируем сессии по ID пользователя и дате посещения
  145.     # группируем по ID и находим первые значения session_start и channel
  146.     # столбец с временем первого посещения назовём first_ts
  147.     # от англ. first timestamp — первая временная отметка
  148.     profiles = (
  149.         sessions.sort_values(by=['user_id', 'session_start'])
  150.         .groupby('user_id')
  151.         .agg({'session_start': 'first', 'channel': 'first'})
  152.         .rename(columns={'session_start': 'first_ts'})
  153.         .reset_index()  # возвращаем user_id из индекса
  154.     )
  155.     # определяем дату первого посещения
  156.     # и первый день месяца, в который это посещение произошло
  157.     # эти данные понадобятся для когортного анализа
  158.     profiles['dt'] = profiles['first_ts'].dt.date
  159.     profiles['month'] = profiles['first_ts'].astype('datetime64[M]')
  160.     return profiles
  161. #Вызовем функцию get_profiles(), чтобы составить профили пользователей по данным сессий из датафрейма sessions:
  162.  
  163. profiles = get_profiles(sessions)
  164. profiles
  165. user_id first_ts    channel dt  month
  166. 0   10964006    2019-05-12 04:50:17 Yandex  2019-05-12  2019-05-01
  167. 1   12358165    2019-05-10 23:16:24 Yandex  2019-05-10  2019-05-01
  168. 2   12545358    2019-05-05 19:22:46 Organic 2019-05-05  2019-05-01
  169. 3   16165560    2019-05-10 20:29:59 Yandex  2019-05-10  2019-05-01
  170. 4   17733464    2019-05-12 11:08:25 Organic 2019-05-12  2019-05-01
  171. ... ... ... ... ... ...
  172. 141414  999939571625    2019-05-08 17:47:00 Yandex  2019-05-08  2019-05-01
  173. 141415  999954663782    2019-05-04 09:57:28 AnotherSource   2019-05-04  2019-05-01
  174. 141416  999957797889    2019-05-14 21:54:26 Yandex  2019-05-14  2019-05-01
  175. 141417  999974288578    2019-05-07 03:42:53 Organic 2019-05-07  2019-05-01
  176. 141418  999996691258    2019-05-05 09:27:58 AnotherSource   2019-05-05  2019-05-01
  177. 141419 rows × 5 columns
  178.  
  179. #Результат — 141419 пользовательских профилей, в каждом из которых есть данные о дате первого посещения и рекламном источнике, который мотивировал пользователя посетить интернет-магазин. Такие данные значительно упрощают дальнейший анализ.
  180.  
  181. #Имея готовые профили пользователей, легко узнать количество привлечённых каждым источником посетителей. Достаточно сгруппировать профили по рекламному каналу и посчитать количество уникальных ID функцией nunique():
  182.  
  183. profiles.groupby('channel').agg({'user_id': 'nunique'})
  184. user_id
  185. channel
  186. AnotherSource   24751
  187. Organic 69288
  188. Yandex  47380
  189. #Или построить график, отображающий динамику привлечения новых пользователей по каждому из рекламных каналов. Применим метод plot():
  190.  
  191. import matplotlib.pyplot as plt
  192. %matplotlib inline
  193. profiles.pivot_table(
  194.     index='dt',  # даты первых посещений
  195.     columns='channel',  # источники переходов
  196.     values='user_id',  # ID пользователей
  197.     aggfunc='nunique'  # подсчёт уникальных значений
  198. ).plot(figsize=(15, 5), grid=True)
  199. plt.show()
  200.  
  201. #В первые две недели мая новые посетители чаще всего приходили из источника Organic, а реже всего — из AnotherSource. Все источники отличаются стабильностью: количество привлекаемых ими пользователей не опускается ниже определённого уровня. Например, Yandex в исследуемый период привлекал — приблизительно — не менее 3000 новых пользователей в день.
  202.  
  203.  
  204. # 1.
  205. #Создайте расширенные профили посетителей магазина «Читать не вредно».
  206. #Для этого измените функцию get_profiles() из теории так, чтобы кроме источника перехода на сайт она возвращала устройство (device) и регион (region) первого посещения. Передайте обновлённой функции данные из файла sessions.csv.
  207. #Затем определите, сколько пользователей заходили на сайт с каждого устройства. Результат отсортируйте по убыванию количества посетителей и выведите на экран.
  208. #Структуру sessions.csv можно посмотреть во вкладке.import pandas as pd
  209.  
  210. sessions = pd.read_csv('sessions.csv')
  211. sessions['session_start'] = pd.to_datetime(sessions['session_start'])
  212.  
  213. def get_profiles(sessions):
  214.  
  215.     profiles = (
  216.         sessions.sort_values(by=['user_id', 'session_start'])
  217.         .groupby('user_id')
  218.         .agg(
  219.             {
  220.                 'session_start': 'first',
  221.                 'channel': 'first',
  222.                 'device': 'first',
  223.                 'region': 'first'# допишите код
  224.                 # допишите код
  225.             }
  226.         )
  227.         .rename(columns={'session_start': 'first_ts'})
  228.         .reset_index()
  229.     )
  230.  
  231.     profiles['dt'] = profiles['first_ts'].dt.date
  232.     profiles['month'] = profiles['first_ts'].astype('datetime64[M]')
  233.  
  234.     return profiles
  235.  
  236. profiles = get_profiles(sessions)
  237.  
  238. profiles = profiles.groupby('device').agg({'user_id': 'nunique'}).sort_values(by = 'user_id', ascending = False)
  239.  
  240. print(profiles)
  241.    
  242. #2.
  243. 3В дополнение к журналу пользовательских сессий интернет-магазин «Читать не вредно» передал вам файл с данными о всех покупках пользователей — book_orders.csv.
  244. #Вот его структура:
  245. #user_id — уникальный идентификатор пользователя,
  246. #event_dt — дата покупки,
  247. #revenue — сумма покупки.
  248. #Обогатите пользовательские профили информацией о покупках: добавьте в профили признак payer, который принимает значение True, если идентификатор пользователя есть среди покупателей, и значение False в ином случае.
  249.  
  250. import pandas as pd
  251.  
  252. sessions = pd.read_csv('sessions.csv')
  253. sessions['session_start'] = pd.to_datetime(sessions['session_start'])
  254.  
  255. orders = pd.read_csv('book_orders.csv')
  256. orders['event_dt'] = pd.to_datetime(orders['event_dt'])
  257.  
  258. # добавили второй аргумент
  259. def get_profiles(sessions, orders):
  260.  
  261.     profiles = (
  262.         sessions.sort_values(by=['user_id', 'session_start'])
  263.         .groupby('user_id')
  264.         .agg(
  265.             {
  266.                 'session_start': 'first',
  267.                 'channel': 'first',
  268.                 'device': 'first',
  269.                 'region': 'first',
  270.             }
  271.         )
  272.         .rename(columns={'session_start': 'first_ts'})
  273.         .reset_index()
  274.     )
  275.  
  276.     profiles['dt'] = profiles['first_ts'].dt.date
  277.     profiles['month'] = profiles['first_ts'].astype('datetime64[M]')
  278.    
  279.     # проверьте, есть ли ID пользователей из profiles в orders
  280.     profiles['payer'] = profiles['user_id'].isin(orders['user_id'].unique()) # ваш код здесь
  281.  
  282.     return profiles
  283.  
  284. # строим профили по двум наборам данных
  285. profiles = get_profiles(sessions, orders)
  286.  
  287. print(
  288.     profiles.groupby('region')
  289.     .agg({'payer': 'mean'})
  290.     .sort_values(by='payer', ascending=False)
  291. )# допишите код
  292.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement