File size: 8,645 Bytes
5bfe767
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3edbda0
 
 
 
 
 
 
 
 
 
 
 
266eb11
3edbda0
 
 
 
5bfe767
 
3edbda0
5bfe767
3edbda0
5bfe767
 
 
3edbda0
 
 
5bfe767
 
266eb11
3edbda0
 
 
5bfe767
 
 
 
 
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
import gradio as gr
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import numpy as np
import statsmodels.api as sm
import os

# Load main metrics
df = pd.read_csv("data/india_growth_metrics.csv")
df.columns = df.columns.str.strip()
cities = df['City'].unique()
metrics = df.columns[1:-1]  # Exclude City and Gini Coefficient

# Cluster setup
scaler = StandardScaler()
cluster_data = scaler.fit_transform(df[metrics])
kmeans = KMeans(n_clusters=4, random_state=0).fit(cluster_data)
df['Cluster'] = kmeans.labels_

def create_bar_chart(selected_cities, selected_metric):
    """Create bar chart for selected cities and metric"""
    if not selected_cities or not selected_metric:
        return None
    
    filtered = df[df['City'].isin(selected_cities)]
    fig = px.bar(filtered, x='City', y=selected_metric, color='City', 
                 title=f"{selected_metric} Comparison")
    return fig

def create_radar_chart(selected_cities):
    """Create radar chart for selected cities"""
    if not selected_cities:
        return None
    
    radar_df = df[df['City'].isin(selected_cities)].set_index('City')
    melted = radar_df[metrics].reset_index().melt(id_vars='City', var_name='Metric', value_name='Value')
    fig = px.line_polar(melted, r='Value', theta='Metric', color='City', 
                        line_close=True, title="Radar View")
    fig.update_traces(fill='toself')
    return fig

def create_correlation_matrix(selected_cities):
    """Create correlation matrix for selected cities"""
    if not selected_cities:
        return None
    
    corr = df[df['City'].isin(selected_cities)][metrics].corr()
    fig = px.imshow(corr, text_auto=True, title="Correlation Matrix")
    return fig

def generate_ai_insights(selected_cities):
    """Generate AI insights for selected cities"""
    if not selected_cities:
        return "Please select cities to generate insights."
    
    insights = []
    for city in selected_cities:
        city_data = df[df['City'] == city]
        if not city_data.empty:
            highest = city_data[metrics].idxmax(axis=1).values[0]
            lowest = city_data[metrics].idxmin(axis=1).values[0]
            insights.append(f"๐Ÿ™๏ธ **{city}** excels in **{highest}** but needs improvement in **{lowest}**.")
    
    return "\n".join(insights) if insights else "No insights available."

def find_twin_cities(selected_cities):
    """Find twin cities for selected cities"""
    if not selected_cities:
        return "Please select cities to find twin cities."
    
    twin_info = []
    for city in selected_cities:
        city_data = df[df['City'] == city]
        if not city_data.empty:
            city_vec = city_data[metrics].values
            df_temp = df.copy()
            df_temp['distance'] = np.linalg.norm(df_temp[metrics].values - city_vec, axis=1)
            nearest = df_temp[df_temp['City'] != city].sort_values('distance').iloc[0]['City']
            twin_info.append(f"๐Ÿ™๏ธ **{city}**'s most similar city is **{nearest}**.")
    
    return "\n".join(twin_info) if twin_info else "No twin cities found."

def create_time_series(selected_metric, selected_city):
    """Create time series forecast for selected metric and city"""
    if not selected_metric or not selected_city:
        return None
    
    try:
        time_df = pd.read_csv("data/timeseries.csv", encoding='utf-8-sig')
        time_df.columns = time_df.columns.str.strip()
        time_df['City'] = time_df['City'].str.strip()
        
        fig = go.Figure()
        city_df = time_df[time_df['City'] == selected_city].sort_values('Year')
        city_df['Year'] = pd.to_datetime(city_df['Year'], format='%Y')

        if selected_metric in city_df.columns:
            ts = city_df.set_index('Year')[selected_metric]
            fig.add_trace(go.Scatter(x=ts.index, y=ts.values, mode='lines+markers', 
                                   name=selected_metric))
            try:
                model = sm.tsa.ARIMA(ts, order=(1, 1, 0)).fit()
                forecast = model.get_forecast(steps=3)
                forecast_index = pd.date_range(start=ts.index[-1] + pd.offsets.YearBegin(), 
                                             periods=3, freq='YS')
                forecast_series = pd.Series(forecast.predicted_mean.values, index=forecast_index)
                fig.add_trace(go.Scatter(x=forecast_series.index, y=forecast_series.values,
                                       mode='lines+markers', name=f"{selected_metric} Forecast",
                                       line=dict(dash='dash')))
            except:
                pass

        fig.update_layout(title=f"Time Series Forecast: {selected_metric} in {selected_city}", 
                         xaxis_title='Year')
        return fig
    except Exception as e:
        return None

def create_cluster_view(metric):
    """Create cluster visualization"""
    if not metric:
        return None
    
    fig = px.scatter(df, x=metric, y='Gini Coefficient', color='Cluster',
                     hover_data=['City'], title="City Clustering")
    return fig

# Create Gradio interface
with gr.Blocks(title="India Growth Metrics Dashboard", theme=gr.themes.Soft()) as demo:
    gr.Markdown("# ๐Ÿ‡ฎ๐Ÿ‡ณ Decode India: Smart AI-Enhanced Dashboard for Growth Metrics")
    gr.Markdown("A powerful interactive dashboard that visualizes and analyzes growth metrics for 35 major Indian cities using AI, time series forecasting, and cluster-based insights.")
    
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### ๐Ÿ“Š Dashboard Controls")
            
            city_selector = gr.Dropdown(
                choices=list(cities),
                value=list(cities[:3]),
                label="Select Cities",
                multiselect=True
            )
            
            metric_selector = gr.Dropdown(
                choices=list(metrics),
                value=metrics[0],
                label="Select Metric"
            )
    
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### ๐Ÿ“ˆ Bar Chart Comparison")
            bar_chart = gr.Plot(label="Bar Chart")
        
        with gr.Column(scale=1):
            gr.Markdown("### ๐ŸŒ Radar Chart")
            radar_chart = gr.Plot(label="Radar Chart")
    
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### ๐Ÿงฎ Correlation Matrix")
            correlation_matrix = gr.Plot(label="Correlation Matrix")
        
        with gr.Column(scale=1):
            gr.Markdown("### ๐ŸŽฏ City Clustering")
            cluster_view = gr.Plot(label="Cluster View")
    
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### ๐Ÿ“ˆ Time Series Forecast")
            time_series = gr.Plot(label="Time Series")
        
        with gr.Column(scale=1):
            gr.Markdown("### ๐Ÿง  AI Insights")
            ai_insights = gr.Markdown(label="AI Insights")
    
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### ๐ŸŒ Twin City Recommendations")
            twin_cities = gr.Markdown(label="Twin Cities")
    
    # Event handlers
    def update_all_outputs(selected_cities, selected_metric):
        # Time series uses the first selected city
        time_series_city = selected_cities[0] if selected_cities else None

        bar_fig = create_bar_chart(selected_cities, selected_metric)
        radar_fig = create_radar_chart(selected_cities)
        corr_fig = create_correlation_matrix(selected_cities)
        cluster_fig = create_cluster_view(selected_metric)
        ai_md = generate_ai_insights(selected_cities)
        twin_md = find_twin_cities(selected_cities)
        ts_fig = create_time_series(selected_metric, time_series_city)

        return bar_fig, radar_fig, corr_fig, cluster_fig, ts_fig, ai_md, twin_md

    # A list of all outputs for convenience
    all_outputs = [bar_chart, radar_chart, correlation_matrix, cluster_view, time_series, ai_insights, twin_cities]

    # Connect inputs to outputs
    city_selector.change(
        fn=update_all_outputs,
        inputs=[city_selector, metric_selector],
        outputs=all_outputs
    )
    
    metric_selector.change(
        fn=update_all_outputs,
        inputs=[city_selector, metric_selector],
        outputs=all_outputs
    )
    
    demo.load(
        fn=update_all_outputs,
        inputs=[city_selector, metric_selector],
        outputs=all_outputs
    )

# Launch the app
if __name__ == "__main__":
    demo.launch()