File size: 10,023 Bytes
12b7a88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import gradio as gr
import re

custom_theme = gr.themes.Base().set(
    body_background_fill="linear-gradient(120deg, #f9fcff 0%, #fef6ff 100%)",
    block_background_fill="white",
    block_shadow="0px 5px 15px rgba(0,0,0,0.06)",
    block_border_width="1px",
    block_border_color="#e6e6e6",
)





# Run predictions
results_df = run_batch_predictions(df, pipe)
# Create a new DataFrame without 'Clusters' and 'Recommendation'
export_df = results_df.drop(columns=[col for col in ['Clusters', 'Recommendation'] if col in results_df.columns])

# Save to CSV
export_df.to_csv('results_summary.csv', index=False)


# Add the constant column
results_df["RecordCount"] = 1


# Extract actions
''''
def extract_actions(html_text):
    if not isinstance(html_text, str):
        return ["No action"]
    text = html_text.replace("<br>", "\n")
    actions = re.findall(r"• (.+)", text)
    return actions if actions else ["No action"]
'''
# Drilldown DataFrame
drilldown_data = []
for _, row in results_df.iterrows():
    churn_pred = row["Churn Prediction"]
    prob= row["Probability"]
    clusters = row["Clusters"]
    if isinstance(clusters, dict):
        for cluster_name, rec_list in clusters.items():
            for rec in rec_list:
                drilldown_data.append({
                    "Churn Prediction": churn_pred,
                    "Cluster": cluster_name,
                    "Recommendation": rec,
                    "Probability": prob
                })

drilldown_df = pd.DataFrame(drilldown_data)

# Chart defaults
px.defaults.template = "plotly_white"
px.defaults.color_discrete_sequence = px.colors.qualitative.Set2

# Helper for numeric KPI cards
def make_numeric_card(title, value, suffix=""):
    fig = go.Figure(go.Indicator(
        mode="number",
        value=value,
        number={'font': {'size': 36}, 'suffix': suffix},
        title={'text': title, 'font': {'size': 16}}
    ))
    fig.update_layout(
        height=140, width=220,
        margin=dict(l=10, r=10, t=25, b=10),
        paper_bgcolor="white"
    )
    return fig

# Build Analytics Figures
def generate_analytics_figs(df):
    figs = {}
    figs["avg_tenure"] = make_numeric_card("Avg Tenure (Months)", df["Tenure in Months"].mean())
    figs["avg_charge"] = make_numeric_card("Avg Monthly Charge ($)", df["Monthly Charge"].mean(), suffix="$")
    figs["avg_data"] = make_numeric_card("Avg Monthly GB Download", df["Avg Monthly GB Download"].mean())

    figs["tenure_hist"] = px.histogram(df, x="Tenure in Months", nbins=20, title="Tenure Distribution")
    figs["age_hist"] = px.histogram(df, x="Age", nbins=20, title="Age Distribution")

    figs["contract_pie"] = px.pie(df, names="Contract", hole=0.4, title="Contract Types")
    figs["dependents_donut"] = px.pie(df, names="Number of Dependents", hole=0.4, title="Dependents Distribution")
    figs["senior_pie"] = px.pie(df, names="Senior Citizen", hole=0.4, title="Senior Citizen Ratio")
    figs["streaming_pie"] = px.pie(df, names="Streaming Movies", hole=0.4, title="Streaming Movies Adoption")
    figs["security_pie"] = px.pie(df, names="Online Security", hole=0.4, title="Online Security Subscription")
    figs["unlimited_pie"] = px.pie(df, names="Unlimited Data", hole=0.4, title="Unlimited Data Adoption")

    referrals_df = df["Number of Referrals"].value_counts().reset_index()
    referrals_df.columns = ["Number of Referrals", "count"]
    figs["referrals_bar"] = px.bar(
        referrals_df,
        x="Number of Referrals",
        y="count",
        title="Referrals Count Distribution",
        labels={"Number of Referrals": "Number of Referrals", "count": "Count"}
    )

    for f in figs.values():
        f.update_layout(margin=dict(l=20, r=20, t=40, b=20))

    return figs

analytics_figs = generate_analytics_figs(results_df)

# Drilldown Chart
def generate_drilldown_chart():
    if drilldown_df.empty:
        fig = px.treemap(names=["No data"], parents=[""], values=[1], title="No recommendations yet")
        return fig
    fig = px.treemap(
        drilldown_df,
        path=['Churn Prediction', 'Cluster', 'Recommendation'],
        values=None,
        title="Recommendations by Churn Prediction & Cluster",
    )
    fig.update_traces(
        textinfo='label+percent parent',
        hovertemplate="<b>%{label}</b><br>Customers: %{value}<br>Percentage of parent: %{percentParent:.1%}<extra></extra>"
    )
    fig.update_layout(
        margin=dict(l=20, r=20, t=50, b=20),
        title_font=dict(size=18)
    )
    return fig

# Customer Details


def get_customer_details(customer_id):
    row = results_df[results_df["Customer ID"] == customer_id].iloc[0]
    prediction = row["Churn Prediction"]
    clusters = row["Clusters"]
    prob= row["Probability"]
    # Convert decimal probability → percentage
    pct_value = float(prob) * 100    # numeric percentage, e.g. 82.3
    pct = f"{pct_value:.0f}%"        # string percentage, e.g. "82%"

    # Categorize risk
    if pct_value < 30:
        risk_level = "Low"
    elif pct_value < 60:
        risk_level = "Medium"
    else:
        risk_level = "High"

    # Corrected line
    churn_risk = f"{risk_level} ({pct})"


    # Build recommendations with cluster names
    if isinstance(clusters, dict):
        rec_lines = []
        for cluster_name, rec_list in clusters.items():
            for rec in rec_list:
                rec_lines.append(f"<b>{cluster_name}:</b> {rec}")
        recommendations_html = "<br>• ".join(rec_lines) if rec_lines else "No recommendations"
    else:
        recommendations_html = "No recommendations"

    selected_features = [
        'Contract', 'Tenure in Months', 'Age', 'Number of Referrals',
        'Monthly Charge', 'Number of Dependents', 'Senior Citizen',
        'Streaming Movies', 'Online Security', 'Avg Monthly GB Download',
        'Unlimited Data'
    ]
    
    # Table with customer features
    table_html = "<table style='width:100%; border-collapse: collapse;'>"
    table_html += "<tbody>"
    for col in selected_features:
        table_html += f"<tr><td style='padding:8px; border:1px solid #ddd; font-weight:600;'>{col}</td>"
        table_html += f"<td style='padding:8px; border:1px solid #ddd;'>{row[col]}</td></tr>"
    table_html += "</tbody></table>"

    # Build full HTML with recommendations **outside** the table
    full_html = (
        f"<b>Churn Risk:</b> {churn_risk}<br><br>"
        f"<b>Recommendations:</b><br>• {recommendations_html}<br><br>"
        f"<b>Customer Details:</b><br>{table_html}"
    )
    return full_html



# Gradio App
with gr.Blocks(
    theme=custom_theme,
    title="CRM Churn Dashboard",
    css="""
        /* FORCE LIGHT MODE */
        :root {
            --color-background: #ffffff !important;
            --color-border: #e6e6e6 !important;
            --color-text: #000000 !important;
            --body-background-fill: linear-gradient(120deg, #f9fcff 0%, #fef6ff 100%) !important;
    
            /* Override dark mode variables */
            --dark-mode: 0 !important;
            --neutral-900: #000000 !important;
            --neutral-800: #1a1a1a !important;
            --neutral-700: #2a2a2a !important;
            --neutral-600: #3a3a3a !important;
            --neutral-500: #777 !important;
            --neutral-400: #aaa !important;
            --neutral-300: #ccc !important;
            --neutral-200: #eee !important;
            --neutral-100: #fafafa !important;
        }

        body {
            background: linear-gradient(120deg, #f9fcff 0%, #fef6ff 100%) !important;
        }

        /* Force blocks to be light */
        .gr-block, .gr-panel, .gr-box, .gr-container {
            background: white !important;
            color: black !important;
        }

        /* Dropdowns, inputs, etc. */
        input, select, textarea {
            background: white !important;
            color: black !important;
            border: 1px solid #ddd !important;
        }
    """
) as demo:



    gr.Markdown("## 📊 CRM Analytics Dashboard")

    with gr.Tabs():
        # Actions Insights tab
        with gr.TabItem("Actions Overview"):
            gr.Markdown("### Drilldown of Recommendations by Cluster")
            drilldown_plot = gr.Plot(value=generate_drilldown_chart())

        # Analytics Dashboard tab (donut style, original font)
        with gr.TabItem("Analytics Dashboard"):
            gr.Markdown("### Customer Base Analytics Overview")
            with gr.Row():
                gr.Plot(value=analytics_figs["avg_tenure"])
                gr.Plot(value=analytics_figs["avg_charge"])
                gr.Plot(value=analytics_figs["avg_data"])
            with gr.Row():
                gr.Plot(value=analytics_figs["tenure_hist"])
                gr.Plot(value=analytics_figs["age_hist"])
            with gr.Row():
                gr.Plot(value=analytics_figs["contract_pie"])
                gr.Plot(value=analytics_figs["dependents_donut"])
            with gr.Row():
                gr.Plot(value=analytics_figs["senior_pie"])
                gr.Plot(value=analytics_figs["streaming_pie"])
            with gr.Row():
                gr.Plot(value=analytics_figs["security_pie"])
                gr.Plot(value=analytics_figs["unlimited_pie"])
                gr.Plot(value=analytics_figs["referrals_bar"])

        # Customer Insights tab
        with gr.TabItem("CRM Details"):
            gr.Markdown("### Customer-Level Predictions & Recommendations")
            customer_dropdown = gr.Dropdown(
                choices=results_df["Customer ID"].tolist(),
                value=results_df["Customer ID"].iloc[0],
                label="Select Customer"
            )
            customer_output = gr.HTML()
            customer_dropdown.change(
                fn=get_customer_details,
                inputs=customer_dropdown,
                outputs=customer_output
            )

demo.launch(share=True)