customeranalytics 0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. customeranalytics/__init__.py +319 -0
  2. customeranalytics/configs.py +480 -0
  3. customeranalytics/data_storage_configurations/__init__.py +245 -0
  4. customeranalytics/data_storage_configurations/data_access.py +165 -0
  5. customeranalytics/data_storage_configurations/data_works_pipeline.py +207 -0
  6. customeranalytics/data_storage_configurations/es_create_index.py +544 -0
  7. customeranalytics/data_storage_configurations/logger.py +36 -0
  8. customeranalytics/data_storage_configurations/query_es.py +157 -0
  9. customeranalytics/data_storage_configurations/reports.py +684 -0
  10. customeranalytics/data_storage_configurations/schedule_data_integration.py +355 -0
  11. customeranalytics/docs/queries.yaml +245 -0
  12. customeranalytics/docs/web_configs.yaml +2 -0
  13. customeranalytics/exploratory_analysis/__init__.py +109 -0
  14. customeranalytics/exploratory_analysis/churn.py +232 -0
  15. customeranalytics/exploratory_analysis/cohorts.py +535 -0
  16. customeranalytics/exploratory_analysis/descriptive_statistics.py +470 -0
  17. customeranalytics/exploratory_analysis/funnels.py +407 -0
  18. customeranalytics/exploratory_analysis/product_analytics.py +340 -0
  19. customeranalytics/exploratory_analysis/promotion_analytics.py +299 -0
  20. customeranalytics/exploratory_analysis/rfm.py +202 -0
  21. customeranalytics/exploratory_analysis/sample_data/sample_data_avg_order_count_per_promo_per_cust.csv +99 -0
  22. customeranalytics/exploratory_analysis/sample_data/sample_data_chart_1_search.csv +2 -0
  23. customeranalytics/exploratory_analysis/sample_data/sample_data_chart_2_search.csv +46 -0
  24. customeranalytics/exploratory_analysis/sample_data/sample_data_chart_3_search.csv +2 -0
  25. customeranalytics/exploratory_analysis/sample_data/sample_data_chart_4_search.csv +2 -0
  26. customeranalytics/exploratory_analysis/sample_data/sample_data_churn.csv +2 -0
  27. customeranalytics/exploratory_analysis/sample_data/sample_data_churn_weekly.csv +10 -0
  28. customeranalytics/exploratory_analysis/sample_data/sample_data_client_feature_predicted.csv +1590 -0
  29. customeranalytics/exploratory_analysis/sample_data/sample_data_client_kpis.csv +7060 -0
  30. customeranalytics/exploratory_analysis/sample_data/sample_data_clvrfm_anomaly.csv +561 -0
  31. customeranalytics/exploratory_analysis/sample_data/sample_data_clvsegments_amount.csv +8 -0
  32. customeranalytics/exploratory_analysis/sample_data/sample_data_customer_journey.csv +18 -0
  33. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_clv.csv +103 -0
  34. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_downloads.csv +68 -0
  35. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_1_to_2.csv +66 -0
  36. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_2_to_3.csv +64 -0
  37. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_3_to_4.csv +55 -0
  38. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_dimension_values.csv +199 -0
  39. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_funnel.csv +36 -0
  40. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_funnel_downloads.csv +68 -0
  41. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_inorganic_ratio.csv +6070 -0
  42. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_orders.csv +57 -0
  43. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_organic_orders.csv +64 -0
  44. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_products_of_sales.csv +12574 -0
  45. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_promotion_discount.csv +64 -0
  46. customeranalytics/exploratory_analysis/sample_data/sample_data_daily_promotion_revenue.csv +6070 -0
  47. customeranalytics/exploratory_analysis/sample_data/sample_data_dcohort_anomaly.csv +6 -0
  48. customeranalytics/exploratory_analysis/sample_data/sample_data_dcohort_anomaly_2.csv +118 -0
  49. customeranalytics/exploratory_analysis/sample_data/sample_data_deliver.csv +47 -0
  50. customeranalytics/exploratory_analysis/sample_data/sample_data_deliver_kpis.csv +2 -0
  51. customeranalytics/exploratory_analysis/sample_data/sample_data_deliver_weekday_hour.csv +25 -0
  52. customeranalytics/exploratory_analysis/sample_data/sample_data_dfunnel_anomaly.csv +118 -0
  53. customeranalytics/exploratory_analysis/sample_data/sample_data_dimension_kpis.csv +199 -0
  54. customeranalytics/exploratory_analysis/sample_data/sample_data_dorders_anomaly.csv +85 -0
  55. customeranalytics/exploratory_analysis/sample_data/sample_data_frequency_clusters.csv +6 -0
  56. customeranalytics/exploratory_analysis/sample_data/sample_data_frequency_recency.csv +3740 -0
  57. customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_funnel.csv +25 -0
  58. customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_funnel_downloads.csv +25 -0
  59. customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_inorganic_ratio.csv +2353 -0
  60. customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_orders.csv +25 -0
  61. customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_organic_orders.csv +2353 -0
  62. customeranalytics/exploratory_analysis/sample_data/sample_data_inorganic_orders_per_promotion_per_day.csv +6070 -0
  63. customeranalytics/exploratory_analysis/sample_data/sample_data_kpis.csv +2 -0
  64. customeranalytics/exploratory_analysis/sample_data/sample_data_monetary_clusters.csv +6 -0
  65. customeranalytics/exploratory_analysis/sample_data/sample_data_monetary_frequency.csv +3740 -0
  66. customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_funnel.csv +5 -0
  67. customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_funnel_downloads.csv +5 -0
  68. customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_orders.csv +4 -0
  69. customeranalytics/exploratory_analysis/sample_data/sample_data_most_combined_products.csv +11 -0
  70. customeranalytics/exploratory_analysis/sample_data/sample_data_most_ordered_categories.csv +11 -0
  71. customeranalytics/exploratory_analysis/sample_data/sample_data_most_ordered_products.csv +11 -0
  72. customeranalytics/exploratory_analysis/sample_data/sample_data_order_and_payment_amount_differences.csv +91 -0
  73. customeranalytics/exploratory_analysis/sample_data/sample_data_prepare.csv +101 -0
  74. customeranalytics/exploratory_analysis/sample_data/sample_data_prepare_weekday_hour.csv +25 -0
  75. customeranalytics/exploratory_analysis/sample_data/sample_data_product_kpis.csv +201 -0
  76. customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_amount_accept.csv +11 -0
  77. customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_amount_reject.csv +7 -0
  78. customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_orders_accept.csv +11 -0
  79. customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_orders_reject.csv +11 -0
  80. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_comparison.csv +91 -0
  81. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_kpis.csv +99 -0
  82. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_number_of_customer.csv +99 -0
  83. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_amount_accept.csv +81 -0
  84. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_amount_reject.csv +11 -0
  85. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_orders_accept.csv +55 -0
  86. customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_orders_reject.csv +37 -0
  87. customeranalytics/exploratory_analysis/sample_data/sample_data_purchase_amount_distribution.csv +22 -0
  88. customeranalytics/exploratory_analysis/sample_data/sample_data_recency_clusters.csv +6 -0
  89. customeranalytics/exploratory_analysis/sample_data/sample_data_recency_monetary.csv +3740 -0
  90. customeranalytics/exploratory_analysis/sample_data/sample_data_rfm.csv +2001 -0
  91. customeranalytics/exploratory_analysis/sample_data/sample_data_ride.csv +101 -0
  92. customeranalytics/exploratory_analysis/sample_data/sample_data_ride_weekday_hour.csv +25 -0
  93. customeranalytics/exploratory_analysis/sample_data/sample_data_segmentation.csv +11 -0
  94. customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_daily_before_after_amount.csv +10 -0
  95. customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_daily_before_after_orders.csv +9 -0
  96. customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_monthly_before_after_amount.csv +10 -0
  97. customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_monthly_before_after_orders.csv +11 -0
  98. customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_weekly_before_after_amount.csv +10 -0
  99. customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_weekly_before_after_orders.csv +10 -0
  100. customeranalytics/exploratory_analysis/sample_data/sample_data_user_counts_per_order_seq.csv +47 -0
  101. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_order_per_user.csv +13 -0
  102. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_payment_amount.csv +13 -0
  103. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_session_per_user.csv +13 -0
  104. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_downloads.csv +13 -0
  105. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_1_to_2.csv +13 -0
  106. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_2_to_3.csv +13 -0
  107. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_3_to_4.csv +12 -0
  108. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_funnel.csv +25 -0
  109. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_funnel_downloads.csv +25 -0
  110. customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_orders.csv +10 -0
  111. customeranalytics/ml_process/__init__.py +64 -0
  112. customeranalytics/ml_process/ab_test.py +615 -0
  113. customeranalytics/ml_process/anomaly_detection.py +456 -0
  114. customeranalytics/ml_process/clv_prediction.py +301 -0
  115. customeranalytics/ml_process/customer_segmentation.py +354 -0
  116. customeranalytics/ml_process/delivery_analytics.py +754 -0
  117. customeranalytics/utils.py +186 -0
  118. customeranalytics/web/app/__init__.py +37 -0
  119. customeranalytics/web/app/base/__init__.py +9 -0
  120. customeranalytics/web/app/base/forms.py +16 -0
  121. customeranalytics/web/app/base/models.py +43 -0
  122. customeranalytics/web/app/base/routes.py +126 -0
  123. customeranalytics/web/app/base/static/assets/css/app.css +20 -0
  124. customeranalytics/web/app/base/static/assets/fonts/Inter-Black.woff +0 -0
  125. customeranalytics/web/app/base/static/assets/fonts/Inter-Black.woff2 +0 -0
  126. customeranalytics/web/app/base/static/assets/fonts/Inter-BlackItalic.woff +0 -0
  127. customeranalytics/web/app/base/static/assets/fonts/Inter-BlackItalic.woff2 +0 -0
  128. customeranalytics/web/app/base/static/assets/fonts/Inter-Bold.woff +0 -0
  129. customeranalytics/web/app/base/static/assets/fonts/Inter-Bold.woff2 +0 -0
  130. customeranalytics/web/app/base/static/assets/fonts/Inter-BoldItalic.woff +0 -0
  131. customeranalytics/web/app/base/static/assets/fonts/Inter-BoldItalic.woff2 +0 -0
  132. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBold.woff +0 -0
  133. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBold.woff2 +0 -0
  134. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBoldItalic.woff +0 -0
  135. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
  136. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLight-BETA.woff +0 -0
  137. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLight-BETA.woff2 +0 -0
  138. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLightItalic-BETA.woff +0 -0
  139. customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLightItalic-BETA.woff2 +0 -0
  140. customeranalytics/web/app/base/static/assets/fonts/Inter-Italic.woff +0 -0
  141. customeranalytics/web/app/base/static/assets/fonts/Inter-Italic.woff2 +0 -0
  142. customeranalytics/web/app/base/static/assets/fonts/Inter-Light-BETA.woff +0 -0
  143. customeranalytics/web/app/base/static/assets/fonts/Inter-Light-BETA.woff2 +0 -0
  144. customeranalytics/web/app/base/static/assets/fonts/Inter-LightItalic-BETA.woff +0 -0
  145. customeranalytics/web/app/base/static/assets/fonts/Inter-LightItalic-BETA.woff2 +0 -0
  146. customeranalytics/web/app/base/static/assets/fonts/Inter-Medium.woff +0 -0
  147. customeranalytics/web/app/base/static/assets/fonts/Inter-Medium.woff2 +0 -0
  148. customeranalytics/web/app/base/static/assets/fonts/Inter-MediumItalic.woff +0 -0
  149. customeranalytics/web/app/base/static/assets/fonts/Inter-MediumItalic.woff2 +0 -0
  150. customeranalytics/web/app/base/static/assets/fonts/Inter-Regular.woff +0 -0
  151. customeranalytics/web/app/base/static/assets/fonts/Inter-Regular.woff2 +0 -0
  152. customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBold.woff +0 -0
  153. customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBold.woff2 +0 -0
  154. customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBoldItalic.woff +0 -0
  155. customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBoldItalic.woff2 +0 -0
  156. customeranalytics/web/app/base/static/assets/fonts/Inter-Thin-BETA.woff +0 -0
  157. customeranalytics/web/app/base/static/assets/fonts/Inter-Thin-BETA.woff2 +0 -0
  158. customeranalytics/web/app/base/static/assets/fonts/Inter-ThinItalic-BETA.woff +0 -0
  159. customeranalytics/web/app/base/static/assets/fonts/Inter-ThinItalic-BETA.woff2 +0 -0
  160. customeranalytics/web/app/base/static/assets/fonts/Inter-italic.var.woff2 +0 -0
  161. customeranalytics/web/app/base/static/assets/fonts/Inter-upright.var.woff2 +0 -0
  162. customeranalytics/web/app/base/static/assets/fonts/Inter.var.woff2 +0 -0
  163. customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.eot +0 -0
  164. customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.svg +3570 -0
  165. customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.ttf +0 -0
  166. customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.woff +0 -0
  167. customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.woff2 +0 -0
  168. customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.eot +0 -0
  169. customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.svg +801 -0
  170. customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.ttf +0 -0
  171. customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.woff +0 -0
  172. customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.woff2 +0 -0
  173. customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.eot +0 -0
  174. customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.svg +5028 -0
  175. customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.ttf +0 -0
  176. customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.woff +0 -0
  177. customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.woff2 +0 -0
  178. customeranalytics/web/app/base/static/assets/img/avatars/avatar-1.png +0 -0
  179. customeranalytics/web/app/base/static/assets/img/avatars/avatar-2.png +0 -0
  180. customeranalytics/web/app/base/static/assets/img/avatars/avatar-3.png +0 -0
  181. customeranalytics/web/app/base/static/assets/img/avatars/avatar-4.png +0 -0
  182. customeranalytics/web/app/base/static/assets/img/avatars/avatar-5.png +0 -0
  183. customeranalytics/web/app/base/static/assets/img/avatars/info.jpeg +0 -0
  184. customeranalytics/web/app/base/static/assets/img/icons/customanality.png +0 -0
  185. customeranalytics/web/app/base/static/assets/img/icons/icon-48x48.png +0 -0
  186. customeranalytics/web/app/base/static/assets/js/app.js +2 -0
  187. customeranalytics/web/app/base/static/assets/js/app.js.LICENSE +566 -0
  188. customeranalytics/web/app/base/static/assets/js/app.js.LICENSE.txt +556 -0
  189. customeranalytics/web/app/base/static/assets/js/modules/bootstrap.js +15 -0
  190. customeranalytics/web/app/base/static/assets/js/modules/chartjs.js +4 -0
  191. customeranalytics/web/app/base/static/assets/js/modules/feather.js +8 -0
  192. customeranalytics/web/app/base/static/assets/js/modules/flatpickr.js +4 -0
  193. customeranalytics/web/app/base/static/assets/js/modules/moment.js +4 -0
  194. customeranalytics/web/app/base/static/assets/js/modules/sidebar.js +23 -0
  195. customeranalytics/web/app/base/static/assets/js/modules/theme.js +16 -0
  196. customeranalytics/web/app/base/templates/accounts/login.html +81 -0
  197. customeranalytics/web/app/base/templates/accounts/register.html +80 -0
  198. customeranalytics/web/app/base/templates/includes/footer.html +28 -0
  199. customeranalytics/web/app/base/templates/includes/navigation.html +51 -0
  200. customeranalytics/web/app/base/templates/includes/scripts.html +3 -0
  201. customeranalytics/web/app/base/templates/includes/sidebar.html +146 -0
  202. customeranalytics/web/app/base/templates/layouts/base-fullscreen.html +36 -0
  203. customeranalytics/web/app/base/templates/layouts/base.html +84 -0
  204. customeranalytics/web/app/base/util.py +30 -0
  205. customeranalytics/web/app/home/__init__.py +9 -0
  206. customeranalytics/web/app/home/forms.py +1039 -0
  207. customeranalytics/web/app/home/models.py +438 -0
  208. customeranalytics/web/app/home/profiles.py +310 -0
  209. customeranalytics/web/app/home/routes.py +386 -0
  210. customeranalytics/web/app/home/search.py +288 -0
  211. customeranalytics/web/app/home/static/assets/img/avatars/avatar-1.png +0 -0
  212. customeranalytics/web/app/home/static/assets/img/avatars/avatar-2.png +0 -0
  213. customeranalytics/web/app/home/static/assets/img/avatars/avatar-3.png +0 -0
  214. customeranalytics/web/app/home/static/assets/img/avatars/avatar-4.png +0 -0
  215. customeranalytics/web/app/home/static/assets/img/avatars/avatar-5.png +0 -0
  216. customeranalytics/web/app/home/static/assets/img/icons/customanality.png +0 -0
  217. customeranalytics/web/app/home/static/assets/img/icons/icon-48x48.png +0 -0
  218. customeranalytics/web/app/home/templates/abtest-product.html +280 -0
  219. customeranalytics/web/app/home/templates/abtest-promotion.html +362 -0
  220. customeranalytics/web/app/home/templates/abtest-segments.html +298 -0
  221. customeranalytics/web/app/home/templates/add-data-delivery.html +184 -0
  222. customeranalytics/web/app/home/templates/add-data-product.html +177 -0
  223. customeranalytics/web/app/home/templates/add-data-purchase.html +392 -0
  224. customeranalytics/web/app/home/templates/anomaly.html +261 -0
  225. customeranalytics/web/app/home/templates/clv.html +211 -0
  226. customeranalytics/web/app/home/templates/cohorts.html +308 -0
  227. customeranalytics/web/app/home/templates/customer-segmentation.html +308 -0
  228. customeranalytics/web/app/home/templates/data-es.html +152 -0
  229. customeranalytics/web/app/home/templates/data-execute.html +397 -0
  230. customeranalytics/web/app/home/templates/delivery.html +404 -0
  231. customeranalytics/web/app/home/templates/funnel-customer.html +240 -0
  232. customeranalytics/web/app/home/templates/funnel-session.html +236 -0
  233. customeranalytics/web/app/home/templates/index.html +524 -0
  234. customeranalytics/web/app/home/templates/index2.html +515 -0
  235. customeranalytics/web/app/home/templates/page-403.html +46 -0
  236. customeranalytics/web/app/home/templates/page-404.html +45 -0
  237. customeranalytics/web/app/home/templates/page-500.html +45 -0
  238. customeranalytics/web/app/home/templates/pages-blank.html +33 -0
  239. customeranalytics/web/app/home/templates/pages-sign-in.html +67 -0
  240. customeranalytics/web/app/home/templates/pages-sign-up.html +61 -0
  241. customeranalytics/web/app/home/templates/product.html +203 -0
  242. customeranalytics/web/app/home/templates/profile.html +1009 -0
  243. customeranalytics/web/app/home/templates/rfm.html +254 -0
  244. customeranalytics/web/app/home/templates/search.html +167 -0
  245. customeranalytics/web/app/home/templates/settings.html +205 -0
  246. customeranalytics/web/app/home/templates/stats-desc.html +230 -0
  247. customeranalytics/web/app/home/templates/stats-purchase.html +221 -0
  248. customeranalytics/web/config.py +30 -0
  249. customeranalytics/web/db.sqlite3 +0 -0
  250. customeranalytics/web/run.py +30 -0
  251. customeranalytics-0.1.dist-info/METADATA +1102 -0
  252. customeranalytics-0.1.dist-info/RECORD +254 -0
  253. customeranalytics-0.1.dist-info/WHEEL +4 -0
  254. customeranalytics-0.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,615 @@
1
+ import sys, os, inspect
2
+ import pandas as pd
3
+ import numpy as np
4
+ from itertools import product
5
+
6
+ from ab_test_platform.executor import ABTest
7
+
8
+ currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
9
+ parentdir = os.path.dirname(currentdir)
10
+ sys.path.insert(0, parentdir)
11
+
12
+ from customeranalytics.configs import default_es_port, default_es_host, default_query_date, time_periods
13
+ from customeranalytics.utils import *
14
+ from customeranalytics.data_storage_configurations.query_es import QueryES
15
+ from customeranalytics.ml_process.customer_segmentation import CustomerSegmentation
16
+
17
+
18
+ class ABTests:
19
+ """
20
+ AB Test;
21
+ For more information pls check; https://pypi.org/project/abtest/
22
+
23
+
24
+ """
25
+ def __init__(self,
26
+ temporary_export_path,
27
+ has_product_connection=True,
28
+ has_promotion_connection=True,
29
+ host=None,
30
+ port=None,
31
+ download_index='downloads',
32
+ order_index='orders'):
33
+ """
34
+ ******* ******** *****
35
+ Dimensional AB Test:
36
+ AB Tests must be created individually for dimensions.
37
+ For instance, the Data set contains locations dimension.
38
+ In this case, each location of 'orders' and 'downloads' indexes must be created individually.
39
+ by using 'download_index' and 'order_index' dimension can be assigned in order to create the AB Test.
40
+
41
+ download_index; downloads_location1 this will be the location dimension of
42
+ parameters in order to query downloads indexes; 'location1'.
43
+ download_index; orders_location1 this will be the location dimension of
44
+ parameters in order to query orders indexes; 'location1'.
45
+ ******* ******** *****
46
+
47
+ IF THERE IS NO PROMOTION CONNECTION ON ORDERS INDEX, IT IS NOT STARTED !!
48
+ IF THERE IS NO PRODUCT CONNECTION ON ORDERS INDEX, IT IS NOT STARTED !!
49
+
50
+ :param has_product_connection: Has order index data for products?
51
+ :param has_promotion_connection: Has order index data for promotions?
52
+ :param host: elasticsearch host
53
+ :param port: elasticsearch port
54
+ :param download_index: elasticsearch port
55
+ :param order_index: elasticsearch port
56
+ """
57
+ self.port = default_es_port if port is None else port
58
+ self.host = default_es_host if host is None else host
59
+ self.download_index = download_index
60
+ self.order_index = order_index
61
+ self.has_product_connection = has_product_connection
62
+ self.has_promotion_connection = has_promotion_connection
63
+ self.test = None
64
+ self.query_es = QueryES(port=port, host=host)
65
+ self.cs = CustomerSegmentation(port=self.port, host=self.host, order_index=self.order_index,
66
+ download_index=self.download_index)
67
+ self.data = pd.DataFrame()
68
+ self.products = pd.DataFrame()
69
+ self.promotions = []
70
+ self.u_products = []
71
+ self.max_date = current_date_to_day()
72
+ self.dates = {}
73
+ self.results = {}
74
+ self.time_periods = time_periods[1:]
75
+ self.path = temporary_export_path
76
+ self.features = ["orders", "amount"]
77
+ self.fields = ["client", "session_start_date", "payment_amount", "id"]
78
+ self.fields += ["promotion_id"] if has_promotion_connection else []
79
+ self.fields_products = ["id", "client", "basket", "session_start_date", "payment_amount"]
80
+ self.test_groups = ['segments', 'promotions', "products", "payment_amount"]
81
+ self.confidence_level = [0.01, 0.05]
82
+ self.boostrap_ratio = [0.1, 0.2, 0.3]
83
+ self.decision = pd.DataFrame()
84
+ self.promotion_combinations = []
85
+ self.promotion_comparison = pd.DataFrame()
86
+
87
+ def dimensional_query(self, boolean_query=None):
88
+ if dimension_decision(self.order_index):
89
+ if boolean_query is None:
90
+ boolean_query = [{"term": {"dimension": self.order_index}}]
91
+ else:
92
+ boolean_query += [{"term": {"dimension": self.order_index}}]
93
+ return boolean_query
94
+
95
+ def get_orders_data(self, end_date):
96
+ """
97
+ Purchased orders are collected from Orders Index.
98
+ Session_start_date, client, payment_amount are needed for initializing CLv Prediciton.
99
+ :param end_date: final date to start clv prediction
100
+ """
101
+ self.query_es = QueryES(port=self.port, host=self.host)
102
+ self.query_es.date_queries_builder({"session_start_date": {"lt": end_date}})
103
+ self.query_es.query_builder(fields=self.fields, boolean_queries=self.dimensional_query())
104
+ self.data = pd.DataFrame(self.query_es.get_data_from_es())
105
+
106
+ def dimensional_query(self, boolean_query=None):
107
+ if dimension_decision(self.order_index):
108
+ if boolean_query is None:
109
+ boolean_query = [{"term": {"dimension": self.order_index}}]
110
+ else:
111
+ boolean_query += [{"term": {"dimension": self.order_index}}]
112
+ return boolean_query
113
+
114
+ def get_products(self, end_date):
115
+ """
116
+ Products for purchased orders are collected for Product Type A/B Test.
117
+ 1. Fetch data from orders with filter; actions.purchased: True
118
+ 2. Example of basket dictionary on order document;
119
+ 'basket': {'p_10': {'price': 6.12, 'category': 'p_c_8', 'rank': 109},
120
+ 'p_145': {'price': 12.0, 'category': 'p_c_9', 'rank': 175},
121
+ 'p_168': {'price': 13.12, 'category': 'p_c_10', 'rank': 82},
122
+ 'p_9': {'price': 0.52, 'category': 'p_c_3', 'rank': 9},
123
+ 'p_4': {'price': 3.72, 'category': 'p_c_8', 'rank': 69},
124
+ 'p_104': {'price': 8.88, 'category': 'p_c_10', 'rank': 97},
125
+ 'p_74': {'price': 8.395, 'category': 'p_c_10', 'rank': 35}
126
+ }
127
+ a. Keys of dictionary are products.
128
+ IF THERE IS NO PRODUCTS DATA IS AVAILABLE SKIP THIS PROCESS !!!
129
+ :param end_date: last date of data set
130
+ """
131
+ if self.has_product_connection:
132
+ self.query_es = QueryES(port=self.port, host=self.host)
133
+ self.query_es.date_queries_builder({"session_start_date": {"lt": end_date}})
134
+ self.query_es.query_builder(fields=None,
135
+ boolean_queries=self.dimensional_query([{"term": {"actions.has_basket": True}}]),
136
+ _source=True)
137
+ self.products = self.query_es.get_data_from_es()
138
+ self.products = pd.DataFrame([{col: r['_source'][col] for col in self.fields_products} for r in self.products])
139
+ self.products = self.products.query('basket == basket')
140
+ self.products['products'] = self.products['basket'].apply(lambda x: list(x.keys()) if x == x else None)
141
+ self.products = self.products.query('products == products')
142
+ # get prices
143
+ self.products['price'] = self.products.apply(
144
+ lambda row: [row['basket'][i]['price'] for i in row['products']], axis=1)
145
+ # merge price and product id into the list
146
+ self.products['products'] = self.products.apply(
147
+ lambda row: list(zip([row['id']] * len(row['products']),
148
+ [row['client']] * len(row['products']),
149
+ [row['payment_amount']] * len(row['products']),
150
+ [row['session_start_date']] * len(row['products']),
151
+ row['products'],
152
+ row['price'])), axis=1)
153
+ # concatenate products columns and convert it to dataframe with columns produc_id and price
154
+ self.products = pd.DataFrame(np.concatenate(list(self.products['products']))).rename(
155
+ columns={0: "id", 1: "client", 2: "payment_amount", 3: "session_start_date", 4: "products", 5: "price"})
156
+ # subtract price from payment amount.
157
+ # This will works to see how product of addition affects the total basket of payment amount
158
+ self.products['payment_amount'] = self.products['payment_amount'].apply(lambda x: float(x))
159
+ self.products['price'] = self.products['price'].apply(lambda x: float(x))
160
+ self.products['session_start_date'] = self.products['session_start_date'].apply(lambda x: convert_to_day(x))
161
+
162
+ def get_customer_segments(self):
163
+ """
164
+ Collecting segments of customers from the reports index.
165
+ :param date: given report date
166
+ """
167
+ self.data = pd.merge(self.data, self.cs.fetch()[['client', 'segments']], on='client', how='left')
168
+
169
+ def get_time_period(self, transactions, date_column):
170
+ """
171
+ converting date column of values into the time_periods (hourly weekly, monthly,..)
172
+ :param transactions: total data (orders data with actions)
173
+ :return: data set with time periods
174
+ """
175
+ for p in list(zip(self.time_periods,
176
+ [convert_dt_to_day_str, find_week_of_monday, convert_dt_to_month_str])):
177
+ transactions[p[0]] = transactions[date_column].apply(lambda x: p[1](x))
178
+ transactions[date_column] = transactions[date_column].apply(lambda x: convert_to_date(x))
179
+ return transactions
180
+
181
+ def assign_organic_orders(self):
182
+ """
183
+ fill null promotions to 'organic'
184
+ Check for promotion data connection
185
+ :return:
186
+ """
187
+ if self.has_promotion_connection:
188
+ self.data['promotion_id'] = self.data['promotion_id'].fillna('organic')
189
+
190
+ def get_unique_promotions(self):
191
+ """
192
+ list of unique promotions
193
+ Check for promotion data connection
194
+ """
195
+ if self.has_promotion_connection:
196
+ self.promotions = list(self.data.query("promotion_id != 'organic'")['promotion_id'].unique())
197
+
198
+ def get_unique_products(self):
199
+ """
200
+ list of unique products
201
+ Check for products data connection.
202
+ """
203
+ if self.has_product_connection:
204
+ self.u_products = list(self.products['products'].unique())
205
+
206
+ def generate_test_groups(self):
207
+ """
208
+ generating test groups of AB Test. These groups are not A and B assigning process,
209
+ It is the sub groups of the A and B samples
210
+ :return:
211
+ """
212
+ self.test_groups = [("segments", tp) for tp in self.time_periods]
213
+ if self.has_product_connection:
214
+ self.test_groups += [("products", None)]
215
+ if self.has_promotion_connection:
216
+ self.test_groups += [("promotions", None)]
217
+
218
+ def get_max_order_date(self):
219
+ """
220
+ max order date from session_start_date
221
+ """
222
+ self.max_date = max(list(self.data['daily']))
223
+
224
+ def before_after_day_decision(self, day):
225
+ """
226
+ Before - After Test of date part decision
227
+ :param day: interval date which splits dates into 2 parts before and after.
228
+ :return: datetime
229
+ """
230
+ if day <= self.max_date:
231
+ return day
232
+ else:
233
+ return self.max_date - datetime.timedelta(days=1)
234
+
235
+ def generate_before_after_dates(self, date):
236
+ """
237
+ There 3 types of time periods to calculate dates.
238
+ days, weeks, months
239
+ :param date: current date
240
+ """
241
+ date = self.before_after_day_decision(date)
242
+ _day = convert_to_date(date)
243
+ _week = _day - datetime.timedelta(days=7)
244
+ _month = _day - datetime.timedelta(days=30)
245
+ _prev_day, _prev_week = [tp - datetime.timedelta(days=7) for tp in [_day, _week]]
246
+ _prev_month = _month - datetime.timedelta(days=30)
247
+ self.dates = {"daily": {"before": _prev_day, "after": _day},
248
+ "weekly": {"before": _prev_week, "after": _week},
249
+ "monthly": {"before": _prev_month, "after": _month}}
250
+
251
+ def get_aggregation_func_and_renaming(self, feature):
252
+ """
253
+ There are 2 types of testing features;
254
+ 1. Number of orders per customers on A - B Groups
255
+ 2. Average Payment Amount per customer on A - B Groups
256
+ :param feature: amount or order_count
257
+ :return: aggfunc for groupby function
258
+ """
259
+ if feature == 'orders':
260
+ return {'id': 'count'}, {'id': 'orders'}
261
+ if feature == 'amount':
262
+ return {'payment_amount': 'mean'}, {'payment_amount': 'amount'}
263
+
264
+ def users_promotion_usage(self):
265
+ self.get_unique_promotions()
266
+ get_promo_data = lambda x, p: x.query("promotion_id == @p")
267
+ _first_promo_orders = self.data.query("promotion_id != 'organic'").groupby(["client", "promotion_id"]).agg(
268
+ {"session_start_date": "min"}).reset_index().rename(columns={"session_start_date": "promotion_date"})
269
+ _promos = self.data.groupby(["client", "session_start_date", "id"]).agg(
270
+ {"payment_amount": "mean"}).reset_index()
271
+ befores, afters = [], []
272
+ for p in self.promotions:
273
+ _data = pd.merge(_promos,
274
+ get_promo_data(_first_promo_orders, p),
275
+ on='client', how='left')
276
+ _b = _data.query("session_start_date < promotion_date").drop(
277
+ 'promotion_date', axis=1).rename(columns={"promotion_id": "promotions"})
278
+ _b_clients = list(_b['client'].unique())
279
+ afters.append(_data.query(
280
+ "session_start_date >= promotion_date and client in @_b_clients").drop('promotion_date', axis=1))
281
+ befores.append(_b)
282
+
283
+ return pd.concat(befores), pd.concat(afters).rename(columns={"promotion_id": "promotions"})
284
+
285
+ def users_product_usage(self):
286
+ """
287
+ Calculating the data for product usage.
288
+ 1. There is only payment amount for product usage AB Testing.
289
+ 2. Each customer of transactions before their order that purchased with the related product,
290
+ Each customer of transactions after their order that purchased with the related product,
291
+ 3. Filter out products data for 'before' data-frame
292
+ 4. Collect the customers who has transaction on 'before' data-frame ('before' clients)
293
+ 5. Filter out products data for 'after' data-frame with 'before' clients
294
+ :return: concatenate products pf data-frames
295
+ """
296
+ self.get_unique_products()
297
+ get_product_data = lambda x, p: x.query("products == @p")
298
+ _first_products_orders = self.products.groupby(["client", "products"]).agg(
299
+ {"session_start_date": "min", "price": "first"}).reset_index().rename(
300
+ columns={"session_start_date": "product_date"})
301
+ _products = self.products.groupby(
302
+ ["client", "session_start_date", "id"]).agg({"payment_amount": "mean"}).reset_index()
303
+ befores, afters = [], []
304
+ for p in self.u_products: # iteratively collect data for each product of before and after
305
+ _data = pd.merge(_products,
306
+ get_product_data(_first_products_orders, p),
307
+ on='client', how='left')
308
+ _data = _data.query("products == products")
309
+ _data['payment_amount'] = _data['payment_amount'] - _data['price']
310
+ _data = _data.drop('price', axis=1)
311
+ _b = _data.query("session_start_date < product_date").drop('product_date', axis=1)
312
+ _b_clients = list(_b['client'].unique())
313
+ if len(_b) != 0:
314
+ afters.append(_data.query(
315
+ "session_start_date >= product_date and client in @_b_clients").drop('product_date', axis=1))
316
+ befores.append(_b)
317
+ return pd.concat(befores), pd.concat(afters)
318
+
319
+ def execute_test_grouping(self, data, metric, feature=None):
320
+ """
321
+ This allows us to trigger grouping part.
322
+ :param data: data-frame
323
+ :param metric: amount or order_count
324
+ :param feature: grouping column additional to client
325
+ :return: data-frame
326
+ """
327
+ _agg, renaming = self.get_aggregation_func_and_renaming(metric)
328
+ _groups = [] if feature is None else [feature]
329
+ return data.groupby(["client"] + _groups).agg(_agg).reset_index().rename(columns=renaming)
330
+
331
+ def create_groups(self, metric, periods=None, feature=None, data=None, before_after_test=True):
332
+ """
333
+ This process is the creation of AB Test of A nd B groups
334
+ :param metric: amount of order_count
335
+ :param periods: if there is periodic AB Test such as Daily, Monthly, Weekly
336
+ :param feature: products or promotions
337
+ :param data: if there is data to manipulate
338
+ :param before_after_test: if is before after test
339
+ :return: concatenate data-frame
340
+ """
341
+ if before_after_test:
342
+ if periods in ['daily', 'weekly', 'monthly']:
343
+ _before = self.data[(self.data[periods] >= self.dates[periods]['before']) &
344
+ (self.data[periods] < self.dates[periods]['after'])]
345
+ _after = self.data[self.data[periods] >= self.dates[periods]['after']]
346
+ else:
347
+ if feature == 'promotions':
348
+ _before, _after = self.users_promotion_usage()
349
+ if feature == 'products':
350
+ _before, _after = self.users_product_usage()
351
+
352
+ dfs = []
353
+ for group in [(_before, 'before'), (_after, 'after')]:
354
+ print("group *******", group[1])
355
+ _df = self.execute_test_grouping(data=group[0], metric=metric, feature=feature)
356
+ _df['groups'] = group[1]
357
+ dfs.append(_df)
358
+ return pd.concat(dfs)
359
+
360
+ else:
361
+ data = self.execute_test_grouping(data=data, metric=metric, feature=feature)
362
+ data['groups'] = '-'
363
+ return data
364
+
365
+ def decision_of_test(self, feature, groups, time_periods, comparison=False):
366
+ """
367
+ Creating a column of decision that any increase on A to B
368
+
369
+ :param feature:amount or order_count
370
+ :param groups: products, promotions
371
+ :param time_periods: days, weeks, months
372
+ :param comparison: if only comparing for before and after
373
+ """
374
+ if groups in ['promotions', 'products', 'segments']:
375
+ self.decision = self.decision.groupby(groups).agg({"accept_Ratio": "mean",
376
+ "mean_control": "mean",
377
+ "mean_validation": "mean"}
378
+ ).reset_index().sort_values('accept_Ratio',
379
+ ascending=False)
380
+ column = 'is_' + feature + '_increased_per_' + groups
381
+ if groups == 'segments':
382
+ column = column + "_per_" + time_periods
383
+ if groups is None or comparison:
384
+ self.decision = pd.DataFrame([{
385
+ i: np.mean(self.decision[i]) for i in ['accept_Ratio', 'mean_control', 'mean_validation']
386
+ }])
387
+ if groups is None:
388
+ self.decision['time_period'] = time_periods
389
+ column = 'is_' + feature + '_increased_per_' + time_periods
390
+ if comparison:
391
+ self.decision['promotion_comparison'] = groups[0] + '_' + groups[1]
392
+ column = 'promo_1st_vs_promo_2nd'
393
+
394
+ self.decision[column] = self.decision.apply(
395
+ lambda row: True if row['mean_validation'] > row['mean_control'] and
396
+ row['mean_validation'] > 0.5 else False, axis=1)
397
+
398
+ def decision_of_test_promo_comparison(self, decision, groups):
399
+ """
400
+ Creating a column of decision that any increase on A to B (only for promotion comparison)
401
+ :param decision: data-frame
402
+ :param groups: (promotion_1, promotion_2)
403
+ :return:
404
+ """
405
+ decision = pd.DataFrame([{
406
+ i: np.mean(decision[i]) for i in ['accept_Ratio', 'mean_control', 'mean_validation']
407
+ }])
408
+ decision['promotion_comparison'] = groups[0] + '_' + groups[1]
409
+ decision['1st promo'], decision['2nd promo'] = groups[0], groups[1]
410
+ column = 'promo_1st_vs_promo_2nd'
411
+
412
+ decision[column] = decision.apply(
413
+ lambda row: True if row['mean_validation'] > row['mean_control'] and
414
+ row['mean_validation'] > 0.5 else False, axis=1)
415
+ decision['total_positive_effects'] = decision['promo_1st_vs_promo_2nd'].apply(
416
+ lambda x: 1 if x in ['True', True] else 0)
417
+ return decision
418
+
419
+ def name_of_test(self, is_before_after, fetaure, group, time_period):
420
+ """
421
+
422
+ :param is_before_after: True/False
423
+ :param fetaure: amount, order_count
424
+ :param group: promotion, product
425
+ :param time_period: day, week, month
426
+ :return:
427
+ """
428
+ name = ''
429
+ if group == 'promotions':
430
+ name += 'promotion_usage_'
431
+ if group == 'products':
432
+ name += 'product_usage_'
433
+ if group == 'segments':
434
+ name += 'segments_change_'
435
+ if time_period is not None:
436
+ name += time_period + '_'
437
+ if is_before_after:
438
+ name += 'before_after_'
439
+ name += fetaure
440
+ return name
441
+
442
+ def create_before_after_test(self, date):
443
+ """
444
+ BEFORE - AFTER TEST:
445
+ collect data from before the event and test with after the event.
446
+
447
+ IF THERE IS NO PROMOTION CONNECTION ON ORDERS INDEX, IT IS NOT STARTED !!
448
+ IF THERE IS NO PRODUCT CONNECTION ON ORDERS INDEX, IT IS NOT STARTED !!
449
+
450
+ :param date: recent date
451
+ :return:
452
+ """
453
+ self.results['customer_before_after'] = {}
454
+ for groups in self.test_groups:
455
+ for f in self.features:
456
+ ab = ABTest(data=self.create_groups(metric=f, feature=groups[0], periods=groups[1]),
457
+ test_groups='groups',
458
+ groups=groups[0],
459
+ feature=f,
460
+ exporting_data=False,
461
+ export_path=self.path,
462
+ confidence_level=self.confidence_level,
463
+ boostrap_sample_ratio=self.boostrap_ratio)
464
+ ab.ab_test_init()
465
+ self.decision = ab.get_results()
466
+ self.decision_of_test(f, groups[0], groups[1])
467
+ _name = self.name_of_test(is_before_after=True, fetaure=f, group=groups[0], time_period=groups[1])
468
+ self.insert_into_reports_index(self.decision,
469
+ abtest_type=_name,
470
+ index=self.order_index)
471
+ del ab
472
+
473
+ # self.decision.to_csv(join(self.path, _name + ".csv"), index=False)
474
+
475
+ def execute_promotion_comparison_test(self, p):
476
+ """
477
+ Comparing all combination of Promotions
478
+ :param p: promotion id
479
+ :return: data-frame
480
+ """
481
+ ab = ABTest(data=self.create_groups(data=self.data[self.data['promotion_id'].isin([p[0], p[1]])],
482
+ metric='amount',
483
+ feature='promotion_id', before_after_test=False),
484
+ test_groups='promotion_id',
485
+ feature='amount',
486
+ groups="groups",
487
+ exporting_data=False,
488
+ export_path=self.path,
489
+ confidence_level=self.confidence_level,
490
+ boostrap_sample_ratio=self.boostrap_ratio)
491
+ ab.ab_test_init()
492
+ return self.decision_of_test_promo_comparison(decision=ab.get_results(), groups=[p[0], p[1]])
493
+
494
+ def create_promotion_comparison_test(self, date):
495
+ """
496
+ Comparing all combination of Promotions
497
+ IF THERE IS NO PROMOTION CONNECTION ON ORDERS INDEX, IT IS NOT STARTED !!
498
+ :param date: recent date
499
+ :return:
500
+ """
501
+ if self.has_promotion_connection:
502
+ self.get_unique_promotions()
503
+ self.promotion_combinations = list(filter(lambda x: x[0] != x[1],
504
+ list(product(self.promotions, self.promotions))))
505
+
506
+ for p in self.promotion_combinations:
507
+ self.promotion_comparison = pd.concat([self.promotion_comparison,
508
+ self.execute_promotion_comparison_test(p)])
509
+ self.insert_into_reports_index(self.promotion_comparison,
510
+ abtest_type='promotion_comparison',
511
+ index=self.order_index)
512
+ del self.promotion_comparison
513
+ self.promotion_comparison = None
514
+
515
+ def insert_into_reports_index(self,
516
+ abtest,
517
+ abtest_type,
518
+ index='orders'):
519
+ """
520
+ via query_es.py, each report can be inserted into the reports index with the given format.
521
+ {"id": unique report id,
522
+ "report_date": start_date or current date,
523
+ "report_name": "abtest",
524
+ "index": "main",
525
+ "report_types": {"abtest_type": promotion_comparison || segments_change_monthly_before_after_amount, etc},
526
+ "data": abtest.fillna(0.0).to_dict("records") - dataframe to list of dictionary
527
+ }
528
+ !!! null values are assigned to 0.
529
+
530
+ :param abtest: data set, data frame
531
+ :param start_date: data start date
532
+ :param abtest_type: orders, downloads, customer_journeys
533
+ :param index: dimensionality of data index orders_location1 ; dimension = location1
534
+ """
535
+ list_of_obj = [{"id": np.random.randint(200000000),
536
+ "report_date": convert_to_day(current_date_to_day()).isoformat(),
537
+ "report_name": "abtest",
538
+ "index": get_index_group(index),
539
+ "report_types": {"abtest_type": abtest_type},
540
+ "data": abtest.fillna(0.0).to_dict("records")}]
541
+ self.query_es.insert_data_to_index(list_of_obj, index='reports')
542
+
543
+ def build_in_tests(self, date):
544
+ """
545
+ execute AB Test for given orders index
546
+ :param date: recent date for query data
547
+ :return:
548
+ """
549
+ _date = str(current_date_to_day())[0:10] if date is None else date
550
+ self.get_orders_data(end_date=_date)
551
+ self.get_products(end_date=_date)
552
+ self.data = self.get_time_period(self.data, "session_start_date")
553
+ self.assign_organic_orders()
554
+ self.get_max_order_date()
555
+ self.get_customer_segments()
556
+ self.generate_before_after_dates(convert_to_day(_date))
557
+ self.generate_test_groups()
558
+ self.create_before_after_test(date)
559
+ self.create_promotion_comparison_test(date)
560
+
561
+ def fetch(self, abtest_name, start_date=None):
562
+ """
563
+ Example of cohort_name;
564
+ promotion_comparison
565
+ segments_change_monthly_before_after_amount
566
+ segments_change_monthly_before_after_orders
567
+ segments_change_weekly_before_after_amount
568
+ segments_change_weekly_before_after_orders
569
+ segments_change_daily_before_after_amount
570
+ segments_change_daily_before_after_orders
571
+ product_usage_before_after_amount
572
+ product_usage_before_after_orders
573
+ promotion_usage_before_after_amount
574
+ promotion_usage_before_after_orders
575
+
576
+ Directly, these arguments are sent to elasticsearch reports index in order to fetch related reports.
577
+
578
+ Example AB Test Result;
579
+
580
+ segments accept_Ratio mean_control mean_validation is_amount_increased_per_segments_per_monthly
581
+ 0 lost 0.633333 24.180795 23.996087 False
582
+ 1 at risk 0.616667 23.587849 23.914558 True
583
+ 2 new customers 0.433333 31.431178 31.835731 True
584
+ 3 champions 0.233333 18.990791 20.332927 True
585
+ 4 potential loyalist 0.133333 40.590746 39.738574 False
586
+ 5 can`t lose them 0.066667 24.448692 16.543292 False
587
+ 6 need attention 0.016667 30.248727 26.593158 False
588
+ 7 loyal customers 0.000000 28.847650 29.915854 True
589
+ 8 others 0.000000 33.230453 38.482046 True
590
+ 9 promising 0.000000 42.453413 24.186591 False
591
+
592
+ :param abtest_name: e.g. promotion_comparison
593
+ :param start_date: directly sending start_date to report_date in reports index.
594
+ :return: data data-frame
595
+ """
596
+
597
+ boolean_queries, date_queries = [], []
598
+ boolean_queries = [{"term": {"report_name": "abtest"}},
599
+ {"term": {"report_types.abtest_type": abtest_name}},
600
+ {"term": {"index": get_index_group(self.order_index)}}]
601
+
602
+ if start_date is not None:
603
+ date_queries = [{"range": {"report_date": {"gte": convert_to_iso_format(start_date)}}}]
604
+
605
+ self.query_es = QueryES(port=self.port,
606
+ host=self.host)
607
+ self.query_es.query_builder(fields=None, _source=True,
608
+ date_queries=date_queries,
609
+ boolean_queries=boolean_queries)
610
+ _res = self.query_es.get_data_from_es(index="reports")
611
+ _data = pd.DataFrame()
612
+ if len(_res) != 0:
613
+ _data = pd.DataFrame(_res[0]['_source']['data'])
614
+ return _data
615
+