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.
- customeranalytics/__init__.py +319 -0
- customeranalytics/configs.py +480 -0
- customeranalytics/data_storage_configurations/__init__.py +245 -0
- customeranalytics/data_storage_configurations/data_access.py +165 -0
- customeranalytics/data_storage_configurations/data_works_pipeline.py +207 -0
- customeranalytics/data_storage_configurations/es_create_index.py +544 -0
- customeranalytics/data_storage_configurations/logger.py +36 -0
- customeranalytics/data_storage_configurations/query_es.py +157 -0
- customeranalytics/data_storage_configurations/reports.py +684 -0
- customeranalytics/data_storage_configurations/schedule_data_integration.py +355 -0
- customeranalytics/docs/queries.yaml +245 -0
- customeranalytics/docs/web_configs.yaml +2 -0
- customeranalytics/exploratory_analysis/__init__.py +109 -0
- customeranalytics/exploratory_analysis/churn.py +232 -0
- customeranalytics/exploratory_analysis/cohorts.py +535 -0
- customeranalytics/exploratory_analysis/descriptive_statistics.py +470 -0
- customeranalytics/exploratory_analysis/funnels.py +407 -0
- customeranalytics/exploratory_analysis/product_analytics.py +340 -0
- customeranalytics/exploratory_analysis/promotion_analytics.py +299 -0
- customeranalytics/exploratory_analysis/rfm.py +202 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_avg_order_count_per_promo_per_cust.csv +99 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_1_search.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_2_search.csv +46 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_3_search.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_chart_4_search.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_churn.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_churn_weekly.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_client_feature_predicted.csv +1590 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_client_kpis.csv +7060 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_clvrfm_anomaly.csv +561 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_clvsegments_amount.csv +8 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_customer_journey.csv +18 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_clv.csv +103 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_downloads.csv +68 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_1_to_2.csv +66 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_2_to_3.csv +64 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_cohort_from_3_to_4.csv +55 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_dimension_values.csv +199 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_funnel.csv +36 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_funnel_downloads.csv +68 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_inorganic_ratio.csv +6070 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_orders.csv +57 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_organic_orders.csv +64 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_products_of_sales.csv +12574 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_promotion_discount.csv +64 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_daily_promotion_revenue.csv +6070 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dcohort_anomaly.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dcohort_anomaly_2.csv +118 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_deliver.csv +47 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_deliver_kpis.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_deliver_weekday_hour.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dfunnel_anomaly.csv +118 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dimension_kpis.csv +199 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_dorders_anomaly.csv +85 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_frequency_clusters.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_frequency_recency.csv +3740 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_funnel.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_funnel_downloads.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_inorganic_ratio.csv +2353 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_orders.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_hourly_organic_orders.csv +2353 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_inorganic_orders_per_promotion_per_day.csv +6070 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_kpis.csv +2 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monetary_clusters.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monetary_frequency.csv +3740 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_funnel.csv +5 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_funnel_downloads.csv +5 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_monthly_orders.csv +4 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_most_combined_products.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_most_ordered_categories.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_most_ordered_products.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_order_and_payment_amount_differences.csv +91 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_prepare.csv +101 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_prepare_weekday_hour.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_kpis.csv +201 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_amount_accept.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_amount_reject.csv +7 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_orders_accept.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_product_usage_before_after_orders_reject.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_comparison.csv +91 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_kpis.csv +99 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_number_of_customer.csv +99 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_amount_accept.csv +81 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_amount_reject.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_orders_accept.csv +55 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_promotion_usage_before_after_orders_reject.csv +37 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_purchase_amount_distribution.csv +22 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_recency_clusters.csv +6 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_recency_monetary.csv +3740 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_rfm.csv +2001 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_ride.csv +101 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_ride_weekday_hour.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segmentation.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_daily_before_after_amount.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_daily_before_after_orders.csv +9 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_monthly_before_after_amount.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_monthly_before_after_orders.csv +11 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_weekly_before_after_amount.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_segments_change_weekly_before_after_orders.csv +10 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_user_counts_per_order_seq.csv +47 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_order_per_user.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_payment_amount.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_average_session_per_user.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_downloads.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_1_to_2.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_2_to_3.csv +13 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_cohort_from_3_to_4.csv +12 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_funnel.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_funnel_downloads.csv +25 -0
- customeranalytics/exploratory_analysis/sample_data/sample_data_weekly_orders.csv +10 -0
- customeranalytics/ml_process/__init__.py +64 -0
- customeranalytics/ml_process/ab_test.py +615 -0
- customeranalytics/ml_process/anomaly_detection.py +456 -0
- customeranalytics/ml_process/clv_prediction.py +301 -0
- customeranalytics/ml_process/customer_segmentation.py +354 -0
- customeranalytics/ml_process/delivery_analytics.py +754 -0
- customeranalytics/utils.py +186 -0
- customeranalytics/web/app/__init__.py +37 -0
- customeranalytics/web/app/base/__init__.py +9 -0
- customeranalytics/web/app/base/forms.py +16 -0
- customeranalytics/web/app/base/models.py +43 -0
- customeranalytics/web/app/base/routes.py +126 -0
- customeranalytics/web/app/base/static/assets/css/app.css +20 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Black.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Black.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BlackItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BlackItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Bold.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Bold.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BoldItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-BoldItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBold.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBold.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBoldItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLight-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLight-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLightItalic-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ExtraLightItalic-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Italic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Italic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Light-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Light-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-LightItalic-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-LightItalic-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Medium.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Medium.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-MediumItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-MediumItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Regular.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Regular.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBold.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBold.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBoldItalic.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-SemiBoldItalic.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Thin-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-Thin-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ThinItalic-BETA.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-ThinItalic-BETA.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-italic.var.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter-upright.var.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/Inter.var.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.eot +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.svg +3570 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.ttf +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-brands-400.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.eot +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.svg +801 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.ttf +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-regular-400.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.eot +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.svg +5028 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.ttf +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.woff +0 -0
- customeranalytics/web/app/base/static/assets/fonts/fa-solid-900.woff2 +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-1.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-2.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-3.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-4.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/avatar-5.png +0 -0
- customeranalytics/web/app/base/static/assets/img/avatars/info.jpeg +0 -0
- customeranalytics/web/app/base/static/assets/img/icons/customanality.png +0 -0
- customeranalytics/web/app/base/static/assets/img/icons/icon-48x48.png +0 -0
- customeranalytics/web/app/base/static/assets/js/app.js +2 -0
- customeranalytics/web/app/base/static/assets/js/app.js.LICENSE +566 -0
- customeranalytics/web/app/base/static/assets/js/app.js.LICENSE.txt +556 -0
- customeranalytics/web/app/base/static/assets/js/modules/bootstrap.js +15 -0
- customeranalytics/web/app/base/static/assets/js/modules/chartjs.js +4 -0
- customeranalytics/web/app/base/static/assets/js/modules/feather.js +8 -0
- customeranalytics/web/app/base/static/assets/js/modules/flatpickr.js +4 -0
- customeranalytics/web/app/base/static/assets/js/modules/moment.js +4 -0
- customeranalytics/web/app/base/static/assets/js/modules/sidebar.js +23 -0
- customeranalytics/web/app/base/static/assets/js/modules/theme.js +16 -0
- customeranalytics/web/app/base/templates/accounts/login.html +81 -0
- customeranalytics/web/app/base/templates/accounts/register.html +80 -0
- customeranalytics/web/app/base/templates/includes/footer.html +28 -0
- customeranalytics/web/app/base/templates/includes/navigation.html +51 -0
- customeranalytics/web/app/base/templates/includes/scripts.html +3 -0
- customeranalytics/web/app/base/templates/includes/sidebar.html +146 -0
- customeranalytics/web/app/base/templates/layouts/base-fullscreen.html +36 -0
- customeranalytics/web/app/base/templates/layouts/base.html +84 -0
- customeranalytics/web/app/base/util.py +30 -0
- customeranalytics/web/app/home/__init__.py +9 -0
- customeranalytics/web/app/home/forms.py +1039 -0
- customeranalytics/web/app/home/models.py +438 -0
- customeranalytics/web/app/home/profiles.py +310 -0
- customeranalytics/web/app/home/routes.py +386 -0
- customeranalytics/web/app/home/search.py +288 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-1.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-2.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-3.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-4.png +0 -0
- customeranalytics/web/app/home/static/assets/img/avatars/avatar-5.png +0 -0
- customeranalytics/web/app/home/static/assets/img/icons/customanality.png +0 -0
- customeranalytics/web/app/home/static/assets/img/icons/icon-48x48.png +0 -0
- customeranalytics/web/app/home/templates/abtest-product.html +280 -0
- customeranalytics/web/app/home/templates/abtest-promotion.html +362 -0
- customeranalytics/web/app/home/templates/abtest-segments.html +298 -0
- customeranalytics/web/app/home/templates/add-data-delivery.html +184 -0
- customeranalytics/web/app/home/templates/add-data-product.html +177 -0
- customeranalytics/web/app/home/templates/add-data-purchase.html +392 -0
- customeranalytics/web/app/home/templates/anomaly.html +261 -0
- customeranalytics/web/app/home/templates/clv.html +211 -0
- customeranalytics/web/app/home/templates/cohorts.html +308 -0
- customeranalytics/web/app/home/templates/customer-segmentation.html +308 -0
- customeranalytics/web/app/home/templates/data-es.html +152 -0
- customeranalytics/web/app/home/templates/data-execute.html +397 -0
- customeranalytics/web/app/home/templates/delivery.html +404 -0
- customeranalytics/web/app/home/templates/funnel-customer.html +240 -0
- customeranalytics/web/app/home/templates/funnel-session.html +236 -0
- customeranalytics/web/app/home/templates/index.html +524 -0
- customeranalytics/web/app/home/templates/index2.html +515 -0
- customeranalytics/web/app/home/templates/page-403.html +46 -0
- customeranalytics/web/app/home/templates/page-404.html +45 -0
- customeranalytics/web/app/home/templates/page-500.html +45 -0
- customeranalytics/web/app/home/templates/pages-blank.html +33 -0
- customeranalytics/web/app/home/templates/pages-sign-in.html +67 -0
- customeranalytics/web/app/home/templates/pages-sign-up.html +61 -0
- customeranalytics/web/app/home/templates/product.html +203 -0
- customeranalytics/web/app/home/templates/profile.html +1009 -0
- customeranalytics/web/app/home/templates/rfm.html +254 -0
- customeranalytics/web/app/home/templates/search.html +167 -0
- customeranalytics/web/app/home/templates/settings.html +205 -0
- customeranalytics/web/app/home/templates/stats-desc.html +230 -0
- customeranalytics/web/app/home/templates/stats-purchase.html +221 -0
- customeranalytics/web/config.py +30 -0
- customeranalytics/web/db.sqlite3 +0 -0
- customeranalytics/web/run.py +30 -0
- customeranalytics-0.1.dist-info/METADATA +1102 -0
- customeranalytics-0.1.dist-info/RECORD +254 -0
- customeranalytics-0.1.dist-info/WHEEL +4 -0
- customeranalytics-0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import sys, os, inspect
|
|
4
|
+
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
|
5
|
+
parentdir = os.path.dirname(currentdir)
|
|
6
|
+
sys.path.insert(0, parentdir)
|
|
7
|
+
|
|
8
|
+
from customeranalytics.configs import default_es_port, default_es_host, default_query_date
|
|
9
|
+
from customeranalytics.utils import *
|
|
10
|
+
from customeranalytics.data_storage_configurations.query_es import QueryES
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Cohorts:
|
|
14
|
+
"""
|
|
15
|
+
- From Download to 1st Order Cohort.
|
|
16
|
+
- There are two types of that cohort. Weekly and Daily.
|
|
17
|
+
|
|
18
|
+
***** Examples of Interpret Cohorts; ******
|
|
19
|
+
|
|
20
|
+
Download to 1st Order Daily Cohort;
|
|
21
|
+
|
|
22
|
+
daily 0 1 2 3 4 118 119 120 121
|
|
23
|
+
2021-01-18 501.0 351.0 529.0 393.0 404.0 ... 0.0 0.0 0.0 0.0
|
|
24
|
+
2021-01-19 535.0 356.0 356.0 504.0 412.0 ... 0.0 0.0 0.0 0.0
|
|
25
|
+
2021-01-20 608.0 375.0 387.0 389.0 564.0 ... 0.0 0.0 0.0 0.0
|
|
26
|
+
2021-01-21 422.0 278.0 312.0 320.0 295.0 ... 0.0 0.0 0.0 0.0
|
|
27
|
+
|
|
28
|
+
- 0 - 2021-01-18 ; 501.0 Clients who download in 2021-01-18, have first order in same day
|
|
29
|
+
- 2 - 2021-01-21 ; 312.0 Clients who download in 2021-01-18, have first order after 2 days.
|
|
30
|
+
|
|
31
|
+
Orders From 1st to 2nd Weekly Cohort;
|
|
32
|
+
|
|
33
|
+
weekly 0 1 2 3 9 10 11
|
|
34
|
+
2021-01-18 1586.0 1232.0 877.0 1050.0 ... 0.0 0.0 0.0
|
|
35
|
+
2021-01-25 1054.0 874.0 1121.0 1070.0 ... 0.0 0.0 0.0
|
|
36
|
+
2021-02-01 631.0 876.0 838.0 810.0 ... 0.0 0.0 0.0
|
|
37
|
+
|
|
38
|
+
- 0 - 2021-01-18 ; 1586.0 Clients who have their 1st orders within the week 2021-01-18 (Monday of each week),
|
|
39
|
+
have their 2nd order in the same week (within the week 2021-01-18)
|
|
40
|
+
- 2 - 2021-02-01 ; 838.0 Clients who have their 1st orders within the week 2021-02-01 (Monday of each week),
|
|
41
|
+
have their 2nd order in after 2 weeks (within the week 2021-02-15)
|
|
42
|
+
|
|
43
|
+
Customers Journey Calculation;
|
|
44
|
+
1. Calculate average Hour difference from Download to 1st orders.
|
|
45
|
+
2. Calculate average order
|
|
46
|
+
3. For each calculated average orders, calculate the average purchase amount,
|
|
47
|
+
Example;
|
|
48
|
+
average 2 orders, 1st orders avg 30.3£, 2nd orders avg 33.3£
|
|
49
|
+
4. Calculate average recent hours customers last order to a recent date.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
def __init__(self,
|
|
53
|
+
has_download=True,
|
|
54
|
+
host=None,
|
|
55
|
+
port=None,
|
|
56
|
+
download_index='downloads',
|
|
57
|
+
order_index='orders'):
|
|
58
|
+
"""
|
|
59
|
+
!!!!
|
|
60
|
+
******* ******** *****
|
|
61
|
+
Dimensional Cohorts:
|
|
62
|
+
Cohorts must be created individually for dimensions. For instance, the Data set contains locations dimension.
|
|
63
|
+
In this case, each location of 'orders' and 'downloads' indexes must be created individually.
|
|
64
|
+
by using 'download_index' and 'order_index' dimensions can be assigned in order to create a cohort.
|
|
65
|
+
|
|
66
|
+
download_index; downloads_location1 this will be the location dimension of
|
|
67
|
+
parameters in order to query downloads indexes; 'location1'.
|
|
68
|
+
download_index; orders_location1 this will be the location dimension of
|
|
69
|
+
parameters in order to query orders indexes; 'location1'.
|
|
70
|
+
******* ******** *****
|
|
71
|
+
!!!
|
|
72
|
+
|
|
73
|
+
!!!!
|
|
74
|
+
If a business has no download action (no mobile app) there is no need for download to first-order calculations.
|
|
75
|
+
!!!!
|
|
76
|
+
|
|
77
|
+
:param has_download: True/False related business of requirements
|
|
78
|
+
:param host: elasticsearch host
|
|
79
|
+
:param port: elasticsearch port
|
|
80
|
+
:param download_index: elasticsearch port
|
|
81
|
+
:param order_index: elasticsearch port
|
|
82
|
+
"""
|
|
83
|
+
self.port = default_es_port if port is None else port
|
|
84
|
+
self.host = default_es_host if host is None else host
|
|
85
|
+
self.download_index = download_index
|
|
86
|
+
self.order_index = order_index
|
|
87
|
+
self.query_es = QueryES(port=port, host=host)
|
|
88
|
+
self.has_download = has_download
|
|
89
|
+
self.download_field_data = ["id", "download_date", "client"]
|
|
90
|
+
self.session_orders_field_data = ["id", "session_start_date", "client", "payment_amount"]
|
|
91
|
+
self.downloads = pd.DataFrame()
|
|
92
|
+
self.orders = pd.DataFrame()
|
|
93
|
+
self.download_to_first_order = pd.DataFrame()
|
|
94
|
+
self.time_periods = ['daily', 'weekly']
|
|
95
|
+
self.cohorts = {'downloads_to_1st_order': {_t: None for _t in self.time_periods},
|
|
96
|
+
'orders_from_1_to_2': {_t: None for _t in self.time_periods},
|
|
97
|
+
'orders_from_2_to_3': {_t: None for _t in self.time_periods},
|
|
98
|
+
'orders_from_3_to_4': {_t: None for _t in self.time_periods},
|
|
99
|
+
'customers_journey': {'hourly': None}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
self.order_seq = [1, 2, 3]
|
|
103
|
+
|
|
104
|
+
def get_time_period(self, transactions, date_column):
|
|
105
|
+
"""
|
|
106
|
+
converting date column of values into the time_periods (hourly weekly, monthly,..)
|
|
107
|
+
:param transactions: total data (orders/downloads data with actions)
|
|
108
|
+
:return: data set with time periods
|
|
109
|
+
"""
|
|
110
|
+
for p in list(zip(self.time_periods,
|
|
111
|
+
[convert_dt_to_day_str, find_week_of_monday])):
|
|
112
|
+
transactions[p[0]] = transactions[date_column].apply(lambda x: p[1](x))
|
|
113
|
+
return transactions
|
|
114
|
+
|
|
115
|
+
def dimensional_query(self, boolean_query):
|
|
116
|
+
if dimension_decision(self.order_index):
|
|
117
|
+
boolean_query += [{"term": {"dimension": self.order_index}}]
|
|
118
|
+
return boolean_query
|
|
119
|
+
|
|
120
|
+
def get_data(self, start_date):
|
|
121
|
+
"""
|
|
122
|
+
Collecting orders and downloads data.
|
|
123
|
+
Before query for orders and downloads it checks is there any queried data before.
|
|
124
|
+
query_es.py handles collecting data.
|
|
125
|
+
:param start_date: starting query date
|
|
126
|
+
"""
|
|
127
|
+
start_date = default_query_date if start_date is None else start_date
|
|
128
|
+
if len(self.orders) == 0:
|
|
129
|
+
self.query_es = QueryES(port=self.port, host=self.host)
|
|
130
|
+
self.query_es.query_builder(fields=self.session_orders_field_data,
|
|
131
|
+
boolean_queries=self.dimensional_query([{"term": {"actions.purchased": True}}]),
|
|
132
|
+
date_queries=[{"range": {"session_start_date": {"gte": start_date}}}])
|
|
133
|
+
self.orders = self.query_es.get_data_from_es()
|
|
134
|
+
self.orders = self.get_time_period(pd.DataFrame(self.orders), 'session_start_date')
|
|
135
|
+
if len(self.downloads) == 0:
|
|
136
|
+
if self.has_download:
|
|
137
|
+
|
|
138
|
+
self.query_es = QueryES(port=self.port, host=self.host)
|
|
139
|
+
self.query_es.query_builder(fields=self.download_field_data)
|
|
140
|
+
self.downloads = pd.DataFrame(self.query_es.get_data_from_es(index='downloads'))
|
|
141
|
+
# for the dimensional it is only calculating for dimension of users.
|
|
142
|
+
if dimension_decision(self.order_index):
|
|
143
|
+
self.downloads = self.downloads[self.downloads['client'].isin(list(self.orders['client'].unique()))]
|
|
144
|
+
self.downloads = self.get_time_period(self.downloads, 'download_date')
|
|
145
|
+
self.downloads['download_date'] = self.downloads['download_date'].apply(lambda x: convert_to_date(x))
|
|
146
|
+
|
|
147
|
+
def convert_cohort_to_readable_form(self, cohort, time_period, time_period_back=None):
|
|
148
|
+
"""
|
|
149
|
+
handles the multi-index problem of the pandas data frame. Each cohort has a date column.
|
|
150
|
+
1. splits date column and creates separate data frame.
|
|
151
|
+
2. collects value columns (0, 1, ..110) same ordered as date data-frame and creates separate date-frame
|
|
152
|
+
3. Concatenate date data-frame and values data-frame.
|
|
153
|
+
|
|
154
|
+
time_period_back;
|
|
155
|
+
When only the last 2 weeks of cohort number of assigned on time_period_back will filter out the cohort.
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
:param cohort: cohort with multi-index
|
|
159
|
+
:param time_period: weeky, daily, indicated date column
|
|
160
|
+
:param time_period_back: desire time period (# of days)
|
|
161
|
+
:return: data frame with columns; weekly/daily, 0, 1, 2, ... 100
|
|
162
|
+
"""
|
|
163
|
+
_time_periods = pd.DataFrame(list(cohort[cohort.columns[0]])).rename(columns={0: time_period})
|
|
164
|
+
_cohort = pd.DataFrame(np.array(cohort.drop(cohort.columns[0], axis=1)))
|
|
165
|
+
|
|
166
|
+
if time_period_back is not None:
|
|
167
|
+
time_period_columns, time_period_row = time_period_back, time_period_back
|
|
168
|
+
if max(list(_cohort.columns)) < time_period_back:
|
|
169
|
+
time_period_columns = max(list(_cohort.columns))
|
|
170
|
+
|
|
171
|
+
if len(_time_periods) < time_period_back:
|
|
172
|
+
time_period_row = max(list(_cohort.columns))
|
|
173
|
+
|
|
174
|
+
_cohort = _cohort[range(time_period_columns)]
|
|
175
|
+
cohort = pd.concat([_time_periods, _cohort], axis=1).tail(time_period_row)
|
|
176
|
+
else:
|
|
177
|
+
cohort = pd.concat([_time_periods, _cohort], axis=1)
|
|
178
|
+
return cohort
|
|
179
|
+
|
|
180
|
+
def cohort_download_to_1st_order(self):
|
|
181
|
+
"""
|
|
182
|
+
From Download to 1st order weekly and daily event values.
|
|
183
|
+
1. Each user of the first-order date is created as a data-frame.
|
|
184
|
+
2. Each client of days/weeks between download date and 1st order date is calculated individually.
|
|
185
|
+
3. Date column is created (daily or weekly)
|
|
186
|
+
4. pivoted data;
|
|
187
|
+
- columns; weekday difference between download to 1 order date per user.
|
|
188
|
+
- rows; time period; daily or weekly;
|
|
189
|
+
- values; the number of client count
|
|
190
|
+
|
|
191
|
+
!!!!
|
|
192
|
+
If a business has no download action (no mobile app) there is no need for download to first-order calculations.
|
|
193
|
+
!!!!
|
|
194
|
+
|
|
195
|
+
"""
|
|
196
|
+
try:
|
|
197
|
+
if self.has_download:
|
|
198
|
+
self.download_to_first_order = pd.merge(self.orders,
|
|
199
|
+
self.downloads,
|
|
200
|
+
on='client',
|
|
201
|
+
how='left')
|
|
202
|
+
self.download_to_first_order = self.get_time_period(self.download_to_first_order, 'session_start_date')
|
|
203
|
+
for p in self.time_periods:
|
|
204
|
+
self.download_to_first_order['downloads_to_first_order_' + p] = self.download_to_first_order.apply(
|
|
205
|
+
lambda row: calculate_time_diff(row['download_date'], row[p], period=p), axis=1)
|
|
206
|
+
self.cohorts['downloads_to_1st_order'][p] = self.download_to_first_order.sort_values(
|
|
207
|
+
by=['downloads_to_first_order_' + p, p],
|
|
208
|
+
ascending=True).pivot_table(index=p,
|
|
209
|
+
columns='downloads_to_first_order_'+p,
|
|
210
|
+
aggfunc={"client": lambda x: len(np.unique(x))}
|
|
211
|
+
).reset_index().rename(columns={"client": "client_count"})
|
|
212
|
+
self.cohorts['downloads_to_1st_order'][p] = self.convert_cohort_to_readable_form(
|
|
213
|
+
self.cohorts['downloads_to_1st_order'][p], time_period=p)
|
|
214
|
+
except Exception as e:
|
|
215
|
+
print(e)
|
|
216
|
+
|
|
217
|
+
def get_order_cohort(self, order_seq_num, time_period='daily'):
|
|
218
|
+
"""
|
|
219
|
+
1. Remove users who only have 1 order.
|
|
220
|
+
The main aim here is to create a cohort related to users of 2nd, 3rd and 4th orders.
|
|
221
|
+
2. Filter the .. the order related to 'order_seq_num'.
|
|
222
|
+
3. Create cohort; rows are dates (weekly/daily), columns number of date difference (week or day)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
Example of creation a cohort;
|
|
226
|
+
Let`s check the cohort_orders_from_1_to_2_daily;
|
|
227
|
+
|
|
228
|
+
order_date next_order_date date_diff client
|
|
229
|
+
2021-01-18 2021-01-21 3 c_20
|
|
230
|
+
|
|
231
|
+
This data-frame must be pivoted related to columns order_date, date_diff, the client (count aggregation).
|
|
232
|
+
|
|
233
|
+
:param order_seq_num: 2, 3, 4
|
|
234
|
+
:param time_period: weekly or daily
|
|
235
|
+
:return: cohort data-frame with multi-index
|
|
236
|
+
"""
|
|
237
|
+
index_column = time_period if time_period == 'daily' else 'weekly'
|
|
238
|
+
column_pv = 'diff_days' if time_period == 'daily' else 'diff_weeks'
|
|
239
|
+
orders_from_to = self.orders.query("next_order_date == next_order_date") # removing clients only have 1 order
|
|
240
|
+
orders_from_to = orders_from_to.query("order_seq_num in @order_seq_num") # filter which cohort is executed
|
|
241
|
+
orders_from_to = orders_from_to.sort_values(by=[column_pv, index_column], ascending=True)
|
|
242
|
+
orders_from_to = orders_from_to.pivot_table(index=index_column, # rows are dates (days or mondays of each week)
|
|
243
|
+
columns=column_pv, # day or week difference (integer start with 0)
|
|
244
|
+
aggfunc={"client": lambda x: len(np.unique(x))} # of unique clients
|
|
245
|
+
).reset_index().rename(columns={"client": "client_count"})
|
|
246
|
+
return orders_from_to
|
|
247
|
+
|
|
248
|
+
def cohort_time_difference_and_order_sequence(self, time_period):
|
|
249
|
+
"""
|
|
250
|
+
It is for the ƒinal shape of the cohort related to Orders.
|
|
251
|
+
1. order sequence number is created as a column per user.
|
|
252
|
+
2. next order date is assigned as a newly generated column.
|
|
253
|
+
3. Calculating the time differences between recent order dates and next order dates per user.
|
|
254
|
+
Time difference must be measured related to time periods.
|
|
255
|
+
e.g. daily; day difference, weekly; week difference
|
|
256
|
+
|
|
257
|
+
:param time_period: daily, weekly
|
|
258
|
+
"""
|
|
259
|
+
if 'order_seq_num' not in list(self.orders.columns):
|
|
260
|
+
self.orders['order_seq_num'] = self.orders.sort_values(
|
|
261
|
+
by=['client', time_period], ascending=True).groupby(['client'])['client'].cumcount() + 1
|
|
262
|
+
if 'next_order_date' not in list(self.orders.columns):
|
|
263
|
+
self.orders['next_order_date'] = self.orders.sort_values(
|
|
264
|
+
by=['client', time_period], ascending=True).groupby(['client'])[time_period].shift(-1)
|
|
265
|
+
if 'diff_days' not in list(self.orders.columns):
|
|
266
|
+
self.orders['diff_days'] = self.orders.apply(
|
|
267
|
+
lambda row: calculate_time_diff(row[time_period], row['next_order_date'], 'daily'), axis=1)
|
|
268
|
+
if 'diff_weeks' not in list(self.orders.columns):
|
|
269
|
+
self.orders['diff_weeks'] = self.orders.apply(
|
|
270
|
+
lambda row: calculate_time_diff(row[time_period], row['next_order_date'], 'weekly'), axis=1)
|
|
271
|
+
|
|
272
|
+
def cohort_from_to_order(self):
|
|
273
|
+
"""
|
|
274
|
+
From Order .. to order ... weekly and daily event values.
|
|
275
|
+
- Orders From 1st to 2nd Weekly/Daily
|
|
276
|
+
- Orders From 2nd to 3rd Weekly/Daily
|
|
277
|
+
- Orders From 3rd to 4th Weekly/Daily
|
|
278
|
+
!!! check 'get_order_cohort'
|
|
279
|
+
1. Each client of days/weeks between recent order date and previous order date is calculated individually.
|
|
280
|
+
Example; Orders From 1st to 2nd Weekly/Daily is being calculated;
|
|
281
|
+
Clients orders from 1st to 2nd date differences are calculated
|
|
282
|
+
according to time period (weekly/daily).
|
|
283
|
+
!!! check 'cohort_time_difference_and_order_sequence'
|
|
284
|
+
2. Date column is created (daily or weekly)
|
|
285
|
+
Related to example above, date column will 1st order dates of clients
|
|
286
|
+
3. pivoted data;
|
|
287
|
+
- columns; week - day difference between from ...th order to .. th order date per user.
|
|
288
|
+
- rows; time period; daily or weekly;
|
|
289
|
+
- values; number of client count
|
|
290
|
+
4. This process is initialized iteratively for (1st, 2nd, 3rd, 4th order).
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
for o in self.order_seq:
|
|
294
|
+
for p in self.time_periods:
|
|
295
|
+
try:
|
|
296
|
+
print("order_seq :", o, " || time_periods :", p)
|
|
297
|
+
_cohort_name = "orders_from_" + str(o) + "_to_" + str(o+1)
|
|
298
|
+
self.cohort_time_difference_and_order_sequence(p)
|
|
299
|
+
self.cohorts[_cohort_name][p] = self.get_order_cohort(order_seq_num=[o], time_period=p)
|
|
300
|
+
self.cohorts[_cohort_name][p] = self.convert_cohort_to_readable_form(self.cohorts[_cohort_name][p],
|
|
301
|
+
time_period=p)
|
|
302
|
+
except Exception as e:
|
|
303
|
+
print(e)
|
|
304
|
+
|
|
305
|
+
def customer_average_journey(self):
|
|
306
|
+
"""
|
|
307
|
+
Customers Journey Calculation;
|
|
308
|
+
1. Calculate average Hour difference from Download to 1st orders.
|
|
309
|
+
2. Calculate average order
|
|
310
|
+
3. For each calculated average orders, calculate the average purchase amount,
|
|
311
|
+
Example;
|
|
312
|
+
average 2 orders, 1st orders avg 30.3£, 2nd orders avg 33.3£
|
|
313
|
+
4. Calculate average recent hours customers last order to a recent date.
|
|
314
|
+
"""
|
|
315
|
+
try:
|
|
316
|
+
# convert session start date to datetime format
|
|
317
|
+
self.orders['session_start_date'] = self.orders['session_start_date'].apply(lambda x: convert_to_date(x))
|
|
318
|
+
# e.g. the average is 3; customers of 1st, 2nd 3rd orders have involved the process.
|
|
319
|
+
avg_order_count = int(np.mean(self.orders['order_seq_num']))
|
|
320
|
+
# max date for calculate average recency value (hour).
|
|
321
|
+
max_date = max(self.orders['session_start_date'])
|
|
322
|
+
# first orders per customer
|
|
323
|
+
self.orders['first_order_date'] = self.orders['session_start_date']
|
|
324
|
+
self.orders['last_order_date'] = self.orders['session_start_date']
|
|
325
|
+
first_last_orders = self.orders.groupby("client").agg(
|
|
326
|
+
{"first_order_date": "min", "last_order_date": "max", "order_seq_num": "max"}).reset_index().rename(
|
|
327
|
+
columns={"order_seq_num": "max_order_seq"})
|
|
328
|
+
first_last_orders = pd.merge(self.downloads.drop('id', axis=1), first_last_orders,
|
|
329
|
+
on='client',
|
|
330
|
+
how='left')
|
|
331
|
+
first_last_orders = first_last_orders.query("first_order_date == first_order_date")
|
|
332
|
+
self.orders = pd.merge(self.orders, first_last_orders[['client', 'max_order_seq']], on='client', how='left')
|
|
333
|
+
|
|
334
|
+
first_last_orders = pd.merge(first_last_orders,
|
|
335
|
+
self.orders.query("order_seq_num == 1").groupby(
|
|
336
|
+
"client").agg({"payment_amount": 'mean'}).reset_index().rename(
|
|
337
|
+
columns={"payment_amount": "first_order_amount"})
|
|
338
|
+
, on='client', how='left')
|
|
339
|
+
|
|
340
|
+
first_last_orders['download_to_first_order_hourly'] = first_last_orders.apply(
|
|
341
|
+
lambda row: calculate_time_diff(row['download_date'], row['first_order_date'], 'hourly'), axis=1)
|
|
342
|
+
|
|
343
|
+
first_last_orders['diff_hours_recency'] = first_last_orders.apply(
|
|
344
|
+
lambda row: calculate_time_diff(row['last_order_date'], max_date, 'hourly'), axis=1)
|
|
345
|
+
|
|
346
|
+
x_axis, y_axis = [0, np.mean(first_last_orders['download_to_first_order_hourly'])], [0, np.mean(
|
|
347
|
+
first_last_orders['first_order_amount'])]
|
|
348
|
+
self.orders['download_to_first_order_hourly'] = first_last_orders.apply(
|
|
349
|
+
lambda row: calculate_time_diff(row['download_date'], row['first_order_date'], 'hourly'), axis=1)
|
|
350
|
+
|
|
351
|
+
for o in range(1, avg_order_count): # iterate each order and calculate hour diff. and avg. payment amount.
|
|
352
|
+
_orders = self.orders.query("order_seq_num == @o and next_order_date == next_order_date")
|
|
353
|
+
y_axis.append(np.mean(_orders['payment_amount']))
|
|
354
|
+
x_val = x_axis[-1] + np.mean(list(_orders.query("order_seq_num != 0").groupby("diff_days").agg(
|
|
355
|
+
{"id": "count"}).reset_index().sort_values(by='id', ascending=False)['diff_days'])[0])
|
|
356
|
+
x_axis.append(x_val)
|
|
357
|
+
# recency value is added as the last point on the x-axis
|
|
358
|
+
x_axis += [x_axis[-1] + np.mean(first_last_orders['diff_hours_recency'])]
|
|
359
|
+
y_axis += [0]
|
|
360
|
+
self.cohorts['customers_journey']['hourly'] = pd.DataFrame(
|
|
361
|
+
zip(x_axis, y_axis)).rename(columns={0: "hourly order differences",
|
|
362
|
+
1: "customers` average Purchase Value"})
|
|
363
|
+
except Exception as e:
|
|
364
|
+
print(e)
|
|
365
|
+
|
|
366
|
+
def insert_into_reports_index(self,
|
|
367
|
+
cohort,
|
|
368
|
+
start_date,
|
|
369
|
+
time_period,
|
|
370
|
+
_from=0,
|
|
371
|
+
_to=1,
|
|
372
|
+
cohort_type='orders',
|
|
373
|
+
index='orders'):
|
|
374
|
+
"""
|
|
375
|
+
via query_es.py, each report can be inserted into the reports index with the given format.
|
|
376
|
+
{"id": unique report id,
|
|
377
|
+
"report_date": start_date or current date,
|
|
378
|
+
"report_name": "cohort",
|
|
379
|
+
"index": "main",
|
|
380
|
+
"report_types": {"time_period": weekly, daily, hourly (only for customers_journey)
|
|
381
|
+
"type": orders, downloads,
|
|
382
|
+
"_from": 0 (only for downlods), 1, 2, 3
|
|
383
|
+
"_to": 1, 2, 3, 4
|
|
384
|
+
},
|
|
385
|
+
"data": cohort.fillna(0.0).to_dict("records") - dataframe to list of dictionary
|
|
386
|
+
}
|
|
387
|
+
!!! null values are assigned to 0.
|
|
388
|
+
|
|
389
|
+
:param cohort: data set, data frame
|
|
390
|
+
:param start_date: data start date
|
|
391
|
+
:param time_period: daily, weekly
|
|
392
|
+
:param _from: which order is cohort created from?
|
|
393
|
+
:param _to: which order is cohort created to?
|
|
394
|
+
:param cohort_type: orders, downloads, customer_journeys
|
|
395
|
+
:param index: dimensionality of data index orders_location1 ; dimension = location1
|
|
396
|
+
"""
|
|
397
|
+
list_of_obj = [{"id": np.random.randint(200000000),
|
|
398
|
+
"report_date": current_date_to_day().isoformat() if start_date is None else start_date,
|
|
399
|
+
"report_name": "cohort",
|
|
400
|
+
"index": get_index_group(index),
|
|
401
|
+
"report_types": {"time_period": time_period, "from": _from, "to": _to, "type": cohort_type},
|
|
402
|
+
"data": cohort.fillna(0.0).to_dict("records")}]
|
|
403
|
+
self.query_es.insert_data_to_index(list_of_obj, index='reports')
|
|
404
|
+
|
|
405
|
+
def get_cohort_name(self, cohort_name):
|
|
406
|
+
"""
|
|
407
|
+
cohort_name format; cohort_orders_from_1_to_2_weekly;
|
|
408
|
+
This indicates a weekly cohort related to customers who order their 2nd orders.
|
|
409
|
+
This structured cohort name is split in order to collect _from, _to, _cohort_type filters.
|
|
410
|
+
:param cohort_name: structured cohort name
|
|
411
|
+
:return: _cohort_type, _from, _to (string). These are directly sent to 'fetch' and 'insert_into_reports_index'.
|
|
412
|
+
"""
|
|
413
|
+
_cohort_type = cohort_name.split("_")[1]
|
|
414
|
+
_from, _to = 0, 1
|
|
415
|
+
if _cohort_type == 'orders':
|
|
416
|
+
try:
|
|
417
|
+
_from, _to = int(cohort_name.split("_")[3]), int(cohort_name.split("_")[5])
|
|
418
|
+
except Exception as e:
|
|
419
|
+
print("from - to not in cohort_name !!")
|
|
420
|
+
return _cohort_type, _from, _to
|
|
421
|
+
|
|
422
|
+
def execute_cohort(self, start_date):
|
|
423
|
+
"""
|
|
424
|
+
1. collect downloads and orders data from given indexes.
|
|
425
|
+
2. create From Download to 1st Order Cohort per week and day.
|
|
426
|
+
3. create From 1st/2nd/3rd order To 2nd/3rd/4th order Cohort per week and day.
|
|
427
|
+
4. create customer average journey From Download to the order count
|
|
428
|
+
that is the average order count of all customers.
|
|
429
|
+
5. At the end 9 individual reports are created.
|
|
430
|
+
Here are the created reports after the execution;
|
|
431
|
+
- cohort_downloads_daily
|
|
432
|
+
- cohort_downloads_weekly
|
|
433
|
+
- cohort_orders_from_1_to_2_daily
|
|
434
|
+
- cohort_orders_from_2_to_3_daily
|
|
435
|
+
- cohort_orders_from_3_to_4_daily
|
|
436
|
+
- cohort_orders_from_1_to_2_weekly
|
|
437
|
+
- cohort_orders_from_2_to_3_weekly
|
|
438
|
+
- cohort_orders_from_3_to_4_weekly
|
|
439
|
+
- customers_journey_hourly
|
|
440
|
+
|
|
441
|
+
6. insert each cohort individually into 'reports' index.
|
|
442
|
+
|
|
443
|
+
:param start_date: starting date of collecting data
|
|
444
|
+
"""
|
|
445
|
+
self.get_data(start_date)
|
|
446
|
+
self.cohort_download_to_1st_order()
|
|
447
|
+
self.cohort_from_to_order()
|
|
448
|
+
self.customer_average_journey()
|
|
449
|
+
for _c in self.cohorts:
|
|
450
|
+
if _c != 'customers_journey':
|
|
451
|
+
for p in self.cohorts[_c]:
|
|
452
|
+
_cohort_type, _from, _to = self.get_cohort_name('cohort_' +_c)
|
|
453
|
+
try:
|
|
454
|
+
self.cohorts[_c][p][p] = self.cohorts[_c][p][p].apply(lambda x: str(x)[0:10])
|
|
455
|
+
self.insert_into_reports_index(self.cohorts[_c][p],
|
|
456
|
+
start_date,
|
|
457
|
+
_from=_from,
|
|
458
|
+
_to=_to,
|
|
459
|
+
time_period=p,
|
|
460
|
+
cohort_type=_cohort_type,
|
|
461
|
+
index=self.order_index)
|
|
462
|
+
except Exception as e:
|
|
463
|
+
print(e)
|
|
464
|
+
|
|
465
|
+
try:
|
|
466
|
+
self.insert_into_reports_index(self.cohorts['customers_journey']['hourly'],
|
|
467
|
+
start_date,
|
|
468
|
+
time_period='hourly',
|
|
469
|
+
_from=0,
|
|
470
|
+
_to=100,
|
|
471
|
+
cohort_type='customers_journey',
|
|
472
|
+
index=self.order_index)
|
|
473
|
+
except Exception as e:
|
|
474
|
+
print(e)
|
|
475
|
+
|
|
476
|
+
def fetch(self, cohort_name, start_date=None, end_date=None):
|
|
477
|
+
"""
|
|
478
|
+
Example of cohort_name;
|
|
479
|
+
|
|
480
|
+
cohort_orders_from_1_to_2_daily;
|
|
481
|
+
cohort_type; orders
|
|
482
|
+
time_period; daily
|
|
483
|
+
orders from; 1
|
|
484
|
+
orders to; 2
|
|
485
|
+
|
|
486
|
+
Directly, these arguments are sent to elasticsearch reports index in order to fetch related reports.
|
|
487
|
+
|
|
488
|
+
:param cohort_name: e.g. cohort_orders_from_1_to_2_daily
|
|
489
|
+
:param _from: 1, 2, 3, 4 no need when it is for 'cohort_download_daily' / 'cohort_download_weekly'
|
|
490
|
+
:param _to: 2, 3, 4
|
|
491
|
+
:param start_date: filter cohort date start
|
|
492
|
+
:param end_date: directly sending end_Date to report_date in reports index.
|
|
493
|
+
:return: data data-frame
|
|
494
|
+
"""
|
|
495
|
+
_cohort_type, _from, _to = self.get_cohort_name(cohort_name)
|
|
496
|
+
_time_period = cohort_name.split("_")[-1]
|
|
497
|
+
boolean_queries, date_queries = [], []
|
|
498
|
+
boolean_queries = [{"term": {"report_name": "cohort"}},
|
|
499
|
+
{"term": {"index": get_index_group(self.order_index)}},
|
|
500
|
+
{"term": {"report_types.time_period": _time_period}},
|
|
501
|
+
{"term": {"report_types.type": _cohort_type}},
|
|
502
|
+
{"term": {"report_types.from": _from}},
|
|
503
|
+
{"term": {"report_types.to": _to}}]
|
|
504
|
+
|
|
505
|
+
if end_date is not None:
|
|
506
|
+
date_queries = [{"range": {"report_date": {"lt": convert_to_iso_format(end_date)}}}]
|
|
507
|
+
|
|
508
|
+
self.query_es = QueryES(port=self.port,
|
|
509
|
+
host=self.host)
|
|
510
|
+
self.query_es.query_builder(fields=None, _source=True,
|
|
511
|
+
date_queries=date_queries,
|
|
512
|
+
boolean_queries=boolean_queries)
|
|
513
|
+
_res = self.query_es.get_data_from_es(index="reports")
|
|
514
|
+
_data = pd.DataFrame()
|
|
515
|
+
if len(_res) != 0:
|
|
516
|
+
_data = pd.DataFrame(_res[0]['_source']['data'])
|
|
517
|
+
if start_date is not None:
|
|
518
|
+
_data[_time_period] = _data[_time_period].apply(lambda x: convert_to_date(x))
|
|
519
|
+
if _time_period not in ['yearly', 'hourly']:
|
|
520
|
+
start_date = convert_to_date(start_date)
|
|
521
|
+
_data = _data[_data[_time_period] >= start_date]
|
|
522
|
+
return _data
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|