IanYeo commited on
Commit
5ca0c3c
Β·
1 Parent(s): eca633c

Add customer LTV calculator code

Browse files
Files changed (3) hide show
  1. .gitignore +1 -0
  2. app.py +133 -0
  3. requirements.txt +2 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .vscode/launch.json
app.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+
3
+ import pandas as pd
4
+ import streamlit as st
5
+
6
+
7
+ def months_between_dates(start_date, end_date):
8
+ return (end_date.year - start_date.year) * 12 + (end_date.month - start_date.month)
9
+
10
+ def calculate_lifespan(row):
11
+ if pd.notna(row["Churned"]):
12
+ return (row["Churned"] - row["Date"]).days
13
+ else:
14
+ return (datetime.now() - row["Date"]).days
15
+
16
+ def date_filtered_df(df, start_date, end_date):
17
+ return df[(df['Date'] >= start_date) & (df['Date'] <= end_date)]
18
+
19
+ def average_customer_lifespan_calculation(
20
+ df,
21
+ start_date,
22
+ end_date,
23
+ ) -> float:
24
+ df.sort_values(by=['Customer', 'Date'], inplace=True)
25
+ mask = (df['Date'] >= start_date) & (df['Date'] <= end_date)
26
+ df = df.loc[mask]
27
+ df["Lifespan"] = df.apply(calculate_lifespan, axis=1)
28
+ df = df.dropna(subset=["Value"])
29
+ # Calculate average customer lifespan
30
+ return round(df["Lifespan"].mean(), 0)
31
+
32
+
33
+ def icon_select(value):
34
+ if value >= 7:
35
+ return 'πŸš€'
36
+ elif value >= 5:
37
+ return 'πŸ”₯'
38
+ elif value > 3.5:
39
+ return 'πŸ’€'
40
+ else:
41
+ return 'πŸ’€'
42
+
43
+ @st.cache_data(ttl="5m")
44
+ def get_data(file_link):
45
+
46
+ if 'dl=0' in file_link:
47
+ file_link = file_link.replace('dl=0', 'dl=1')
48
+ all_data_df = pd.read_excel(file_link)
49
+ return all_data_df
50
+
51
+
52
+ st.title('Customer LTV Calculator')
53
+
54
+ file_link = st.text_input(
55
+ 'Link to data file',
56
+ )
57
+
58
+ if not file_link:
59
+ st.stop()
60
+
61
+ all_data_df = get_data(file_link)
62
+
63
+ col1, col2, col3 = st.columns(3)
64
+ with col1:
65
+ start_date = st.date_input(
66
+ 'Start Date:',
67
+ value=pd.to_datetime('2022-09-01'),
68
+ max_value=pd.to_datetime(datetime.now().date()),
69
+ format='DD-MM-YYYY',
70
+ )
71
+ with col2:
72
+ end_date = st.date_input(
73
+ 'End Date:',
74
+ value=pd.to_datetime(datetime.now().date()),
75
+ max_value=pd.to_datetime(datetime.now().date()),
76
+ format='DD-MM-YYYY',
77
+ )
78
+ with col3:
79
+ start_datetime = pd.to_datetime(start_date)
80
+ end_datetime = pd.to_datetime(end_date)
81
+ number_of_months = months_between_dates(start_datetime, end_datetime)
82
+ st.write(str(number_of_months), 'months')
83
+
84
+ calculated_acl = average_customer_lifespan_calculation(
85
+ all_data_df,
86
+ start_datetime,
87
+ end_datetime,
88
+ )
89
+
90
+ if start_date < end_date:
91
+ # Filter the dataframe based on the selected date range
92
+ mask = (all_data_df['Date'] >= start_datetime) & (all_data_df['Date'] <= end_datetime)
93
+ all_data_df = all_data_df.loc[mask]
94
+ else:
95
+ st.error('Error: End date must be after the start date.')
96
+
97
+ all_data_date_filtered = date_filtered_df(all_data_df, start_datetime, end_datetime)
98
+ average_order_size = all_data_date_filtered['Value'].mean()
99
+ formatted_num = "Β£{:,.2f}".format(average_order_size)
100
+ st.write('Average order size (AOS):', str(formatted_num))
101
+
102
+ purchase_frequency = all_data_date_filtered.groupby('Customer')['Date'].nunique()
103
+ average_purchase_frequency_rate = purchase_frequency.mean()/number_of_months
104
+ st.write('Average purchase frequency rate (APFR) per customer per month:', str(round(average_purchase_frequency_rate, 2)))
105
+ customer_value = average_order_size * average_purchase_frequency_rate
106
+ customer_value_formatted = "Β£{:,.2f}".format(customer_value)
107
+ st.write('Customer Value (AOS x APFR):', customer_value_formatted)
108
+
109
+ average_customer_lifespan = 12
110
+ average_customer_lifespan = st.slider(
111
+ f'Average Customer Lifespan (months) - calculated value {calculated_acl} days',
112
+ min_value=1,
113
+ max_value=50,
114
+ step=1,
115
+ value=12,
116
+ )
117
+ customer_lifetime_vale = average_customer_lifespan * customer_value
118
+ customer_lifetime_vale_formatted = "Β£{:,.2f}".format(customer_lifetime_vale)
119
+ st.write('Customer Lifetime Value (CLV):', customer_lifetime_vale_formatted)
120
+
121
+ acquisition_cost = 50
122
+ acquisition_cost = st.slider('Cost of acquisition', min_value=0, max_value=1000, step=10, value=50)
123
+ clv_cac_ratio = customer_lifetime_vale/acquisition_cost
124
+
125
+ all_data_df['year_month'] = all_data_df['Date'].dt.to_period('M')
126
+ all_data_df = all_data_df.sort_values(by='Date')
127
+
128
+ st.write(
129
+ 'CLV to CAC ratio:',
130
+ "{:,.2f}".format(clv_cac_ratio),
131
+ ': 1',
132
+ icon_select(clv_cac_ratio),
133
+ )
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ pandas
2
+ openpyxl