Darkweb007 commited on
Commit
b089304
·
1 Parent(s): 1c6d767

Deploy simplified Gradio app to HuggingFace

Browse files
Documents/Claude/Projects/uber/lyft rider project/surge_pricing_analysis/app.py CHANGED
@@ -1,214 +1,54 @@
1
- """
2
- Gradio dashboard for Surge Pricing Impact Analysis.
3
- Causal inference analysis of marketplace dynamics.
4
- """
5
-
6
  import gradio as gr
7
  import pandas as pd
8
  import numpy as np
9
- import plotly.graph_objects as go
10
- import plotly.express as px
11
-
12
- from src.data_simulator import MarketplaceSimulator
13
- from src.causal_inference import (
14
- PropensityScoreMatching,
15
- SyntheticControlMethod,
16
- InterruptedTimeSeries,
17
- compare_causal_methods
18
- )
19
-
20
-
21
- def generate_analysis(days, surge_mult, surge_freq, demand_elast, supply_elast, seed):
22
- """Generate marketplace data and run causal analysis."""
23
- try:
24
- # Generate data
25
- sim = MarketplaceSimulator(seed=seed)
26
- surge_days = list(np.random.RandomState(seed).choice(
27
- days, size=max(1, int(days * surge_freq)), replace=False
28
- ))
29
-
30
- df = sim.generate_daily_data(
31
- days=days,
32
- surge_multiplier=surge_mult,
33
- surge_days=surge_days,
34
- demand_elasticity=demand_elast,
35
- supply_elasticity=supply_elast
36
- )
37
-
38
- # Summary stats
39
- surge_group = df[df['is_surge'] == 1]
40
- no_surge_group = df[df['is_surge'] == 0]
41
-
42
- summary = f"""
43
- **Simulation Summary**
44
-
45
- Total Days: {len(df)}
46
- Surge Days: {len(surge_group)} ({len(surge_group)/len(df)*100:.1f}%)
47
-
48
- **Completion Rate**
49
- - Surge Days: {surge_group['completion_rate'].mean():.2%}
50
- - No Surge Days: {no_surge_group['completion_rate'].mean():.2%}
51
- - Difference: {(surge_group['completion_rate'].mean() - no_surge_group['completion_rate'].mean()):.2%}
52
-
53
- **Wait Time (minutes)**
54
- - Surge Days: {surge_group['wait_time_minutes'].mean():.1f}
55
- - No Surge Days: {no_surge_group['wait_time_minutes'].mean():.1f}
56
- - Difference: {(surge_group['wait_time_minutes'].mean() - no_surge_group['wait_time_minutes'].mean()):.1f}
57
-
58
- **Driver Earnings ($)**
59
- - Surge Days: ${surge_group['driver_earnings'].mean():.2f}
60
- - No Surge Days: ${no_surge_group['driver_earnings'].mean():.2f}
61
- - Difference: ${(surge_group['driver_earnings'].mean() - no_surge_group['driver_earnings'].mean()):.2f}
62
- """
63
-
64
- # Time series plot
65
- fig_ts = go.Figure()
66
- fig_ts.add_trace(go.Scatter(
67
- x=df['date'],
68
- y=df['completion_rate'],
69
- name='Completion Rate',
70
- mode='lines',
71
- line=dict(color='#4ECDC4', width=2)
72
- ))
73
-
74
- surge_periods = df[df['is_surge'] == 1]
75
- fig_ts.add_trace(go.Scatter(
76
- x=surge_periods['date'],
77
- y=surge_periods['completion_rate'],
78
- mode='markers',
79
- name='Surge Period',
80
- marker=dict(size=8, color='#FF6B6B')
81
- ))
82
-
83
- fig_ts.update_layout(
84
- title='Completion Rate Over Time',
85
- xaxis_title='Date',
86
- yaxis_title='Completion Rate',
87
- hovermode='x unified',
88
- height=400
89
- )
90
-
91
- # Causal analysis
92
- results = compare_causal_methods(df, outcome_col='completion_rate')
93
-
94
- causal_text = "**Causal Inference Results (Completion Rate)**\n\n"
95
- for method, result in results.items():
96
- if 'error' in result:
97
- causal_text += f"- **{method}:** Error - {result['error']}\n"
98
- elif 'ate' in result:
99
- ate = result['ate']
100
- ci_lower = result.get('ci_lower', 0)
101
- ci_upper = result.get('ci_upper', 0)
102
- causal_text += f"- **{method}:** {ate:.4f} (95% CI: [{ci_lower:.4f}, {ci_upper:.4f}])\n"
103
- elif 'level_change' in result:
104
- causal_text += f"- **{method}:** Level Change = {result['level_change']:.4f}\n"
105
-
106
- return summary, fig_ts, causal_text
107
-
108
- except Exception as e:
109
- return f"Error: {str(e)}", None, f"Error in causal analysis: {str(e)}"
110
-
111
-
112
- # Create Gradio interface
113
- with gr.Blocks(title="Surge Pricing Impact Analysis") as demo:
114
- gr.Markdown("""
115
- # 🚗 Surge Pricing Impact Analysis
116
-
117
- **How does surge pricing truly affect rider demand, driver supply, and market equilibrium?**
118
-
119
- This interactive dashboard applies causal inference to isolate the real incremental impact of surge pricing—moving beyond correlation to causation.
120
- """)
121
-
122
- with gr.Row():
123
- with gr.Column(scale=1):
124
- gr.Markdown("### Simulation Parameters")
125
-
126
- days = gr.Slider(
127
- label="Simulation Duration (days)",
128
- minimum=30,
129
- maximum=180,
130
- value=90,
131
- step=10
132
- )
133
-
134
- surge_multiplier = gr.Slider(
135
- label="Surge Multiplier (fare multiplier)",
136
- minimum=1.2,
137
- maximum=3.0,
138
- value=2.5,
139
- step=0.1
140
- )
141
-
142
- surge_frequency = gr.Slider(
143
- label="Surge Frequency (%)",
144
- minimum=5,
145
- maximum=50,
146
- value=15,
147
- step=5
148
- )
149
-
150
- demand_elasticity = gr.Slider(
151
- label="Demand Elasticity",
152
- minimum=-1.0,
153
- maximum=-0.1,
154
- value=-0.5,
155
- step=0.1
156
- )
157
-
158
- supply_elasticity = gr.Slider(
159
- label="Supply Elasticity",
160
- minimum=0.2,
161
- maximum=1.5,
162
- value=0.65,
163
- step=0.1
164
- )
165
-
166
- random_seed = gr.Number(
167
- label="Random Seed",
168
- value=42,
169
- precision=0
170
- )
171
-
172
- analyze_btn = gr.Button("Analyze", scale=2)
173
-
174
- with gr.Column(scale=2):
175
- summary_output = gr.Textbox(
176
- label="Summary Statistics",
177
- lines=15,
178
- interactive=False
179
- )
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  with gr.Row():
182
- timeseries_plot = gr.Plot(label="Time Series: Completion Rate")
183
-
184
- with gr.Row():
185
- causal_output = gr.Textbox(
186
- label="Causal Inference Results",
187
- lines=10,
188
- interactive=False
189
- )
190
-
191
- # Connect button
192
- analyze_btn.click(
193
- fn=generate_analysis,
194
- inputs=[days, surge_multiplier, surge_frequency, demand_elasticity, supply_elasticity, random_seed],
195
- outputs=[summary_output, timeseries_plot, causal_output]
196
- )
197
-
198
- gr.Markdown("""
199
- ---
200
-
201
- ## Methodology
202
-
203
- **Propensity Score Matching (PSM):** Matches surge days to no-surge days based on observable confounders.
204
-
205
- **Synthetic Control Method:** Builds a synthetic "no surge" counterfactual using pre-treatment periods.
206
-
207
- **Interrupted Time Series (ITS):** Estimates level and slope changes at the intervention point.
208
-
209
- [GitHub Repository](https://github.com/data-geek-astronomy/surge_pricing_analysis)
210
- """)
211
-
212
 
213
  if __name__ == "__main__":
214
  demo.launch()
 
 
 
 
 
 
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ def analyze_surge(days, surge_mult, surge_freq):
6
+ """Simple surge pricing analysis."""
7
+ np.random.seed(42)
8
+ dates = pd.date_range('2024-01-01', periods=days, freq='D')
9
+
10
+ base_demand = np.random.normal(500, 50, days)
11
+ base_supply = np.random.normal(300, 30, days)
12
+
13
+ surge_days = np.random.choice(days, int(days * surge_freq), replace=False)
14
+ surge_multiplier = np.ones(days)
15
+ surge_multiplier[surge_days] = surge_mult
16
+
17
+ demand = base_demand * (1 - (surge_mult - 1) * 0.3)
18
+ supply = base_supply * (1 + (surge_mult - 1) * 0.5)
19
+
20
+ completion_rate = np.minimum(supply / demand, 1.0)
21
+ wait_time = 10 * (1 - completion_rate)
22
+
23
+ summary = f"""**Surge Pricing Analysis**
24
+
25
+ Days: {days}
26
+ Surge Events: {len(surge_days)} ({len(surge_days)/days*100:.1f}%)
27
+ Multiplier: {surge_mult}x
28
+
29
+ **Completion Rate**
30
+ Overall: {completion_rate.mean():.2%}
31
+ Surge Days: {completion_rate[surge_days].mean():.2%}
32
+ Normal Days: {completion_rate[~np.isin(range(days), surge_days)].mean():.2%}
33
+
34
+ **Wait Time (minutes)**
35
+ Overall: {wait_time.mean():.1f}
36
+ Surge Days: {wait_time[surge_days].mean():.1f}
37
+ Normal Days: {wait_time[~np.isin(range(days), surge_days)].mean():.1f}"""
38
+
39
+ return summary
40
+
41
+ with gr.Blocks(title="Surge Pricing Analysis") as demo:
42
+ gr.Markdown("# 🚗 Surge Pricing Impact Analysis")
43
+
44
  with gr.Row():
45
+ days = gr.Slider(30, 180, 90, step=10, label="Days")
46
+ surge_mult = gr.Slider(1.2, 3.0, 2.5, step=0.1, label="Multiplier")
47
+ surge_freq = gr.Slider(0.05, 0.5, 0.15, step=0.05, label="Frequency")
48
+
49
+ output = gr.Textbox(label="Results", lines=12)
50
+ analyze_btn = gr.Button("Analyze")
51
+ analyze_btn.click(analyze_surge, [days, surge_mult, surge_freq], output)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  if __name__ == "__main__":
54
  demo.launch()