deschamps-g commited on
Commit
baf55c7
1 Parent(s): ab37175

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +301 -0
  2. requirements.txt +5 -0
app.py ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # docker run -it -v "$(pwd):/home/app" -p 4000:4000 jedha/streamlit-fs-image
2
+ # docker run -it -v "$(pwd):/home/app" -p 4000:4000 jedha/streamlit-fs-image bash
3
+ # docker build . -t NAME_DOCKER
4
+ # docker run -it -p 4000:80 -v "$(pwd):/home/app" -e PORT:80 NAME_DOCKER bash
5
+
6
+ #http://localhost:4000
7
+
8
+ import streamlit as st
9
+ import pandas as pd
10
+ import plotly.express as px
11
+ import plotly.graph_objects as go
12
+ import requests
13
+
14
+
15
+
16
+ DATA_URL = 'https://full-stack-assets.s3.eu-west-3.amazonaws.com/Deployment/get_around_delay_analysis.xlsx'
17
+
18
+ st.set_page_config(layout="wide")
19
+ st.markdown(
20
+ """
21
+ <style>
22
+ .main {
23
+ margin: 0 auto; /* Centers the content */
24
+ max-width: 1100px;
25
+
26
+ }
27
+ </style>
28
+ """,
29
+ unsafe_allow_html=True
30
+ )
31
+
32
+ @st.cache_data
33
+ def load_data():
34
+ data = pd.read_excel(DATA_URL)
35
+ return data
36
+
37
+ data = load_data()
38
+ print('state: ',data['state'].value_counts())
39
+
40
+ st.markdown("""
41
+ <div style="text-align: center;">
42
+ <img src="https://lever-client-logos.s3.amazonaws.com/2bd4cdf9-37f2-497f-9096-c2793296a75f-1568844229943.png" alt="GetAround logo" style="width: 80%;">
43
+ </div>
44
+
45
+ <br>
46
+
47
+ Bienvenue sur la page d'accueil du projet `Get Around`. Notre objectif, après analyse de certains paramètres de locations de voiture, est de créer un modèle
48
+ d'apprentissage machine permettant de déterminer le prix optimal pour une location.
49
+ <br><br><br>
50
+ """, unsafe_allow_html=True)
51
+
52
+
53
+ st.markdown("""---""")
54
+ st.markdown("""<br>""", unsafe_allow_html=True)
55
+ st.subheader("1] Exploration des différents types de location")
56
+
57
+ if st.checkbox('Données brutes'):
58
+ st.subheader('Données brutes')
59
+ st.write(data)
60
+ st.markdown("""
61
+ <div style="background-color: #F5EAF4; padding: 10px;">
62
+
63
+ | Nom du champ | Commentaire |
64
+ |-----------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
65
+ | **rental_id** | Identifiant unique de la location |
66
+ | **car_id** | Identifiant unique de la voiture |
67
+ | **checkin_type** | Flux utilisé pour l'enregistrement et le retour. (c'est-à-dire accès et retour de la voiture) |
68
+ | | - **mobile** : contrat de location signé sur le smartphone du propriétaire |
69
+ | | - **connect** : voiture équipée de la technologie Connect, ouverte par le conducteur avec son smartphone |
70
+ | | *Note : les contrats papier ont été exclus des données car nous n'avons pas de données sur leur retard lors du retour et c'est un cas d'utilisation négligeable* |
71
+ | **state** | annulé signifie que la location n'a pas eu lieu (a été annulée par le conducteur ou le propriétaire). |
72
+ | **delay_at_checkout_in_minutes** | Différence en minutes entre l'heure de fin de location demandée par le conducteur lors de la réservation de la voiture et l'heure réelle à laquelle le conducteur a terminé le retour. Les valeurs négatives signifient que le conducteur a rendu la voiture en avance. |
73
+ | **previous_ended_rental_id** | Identifiant de la location précédente terminée de la voiture (NULL lorsqu'il n'y a pas de location précédente ou que le délai avec la location précédente est supérieur à 12 heures). |
74
+ | **time_delta_with_previous_rental_in_minutes**| Différence en minutes entre l'heure de début prévue de cette location et l'heure de fin prévue de la location précédente (lorsque inférieure à 12 heures, NULL si supérieure). |
75
+
76
+ </div>
77
+ """, unsafe_allow_html=True)
78
+
79
+
80
+
81
+ # data = data.drop(['time_delta_with_previous_rental_in_minutes','previous_ended_rental_id'],axis=1)
82
+
83
+
84
+ st.markdown("""
85
+ <br>
86
+
87
+ Deux types de locations existent : Connect & Mobile.
88
+
89
+ **Mobile** : le conducteur et le propriétaire se rencontrent et signent tous deux le contrat de location sur le smartphone du propriétaire.
90
+
91
+ **Connect** : le conducteur ne rencontre pas le propriétaire et ouvre la voiture avec son smartphone.
92
+
93
+ Répartition des locations selon le type de commande :
94
+ """, unsafe_allow_html=True)
95
+
96
+ fig = px.pie(data, values='car_id', names='checkin_type')
97
+ st.plotly_chart(fig)
98
+
99
+
100
+
101
+ st.subheader("2] Repartition des locations annulées selon le type de commande")
102
+ fig = px.histogram(data, x='checkin_type', color='state')
103
+ st.plotly_chart(fig)
104
+
105
+
106
+ col = 'delay_at_checkout_in_minutes'
107
+ col_mean = data[col].mean()
108
+ col_std = data[col].std()
109
+ # moyenne +/- 2 écarts type
110
+ lower_bound = col_mean - 2 * col_std
111
+ upper_bound = col_mean + 2 * col_std
112
+ print(col_mean,lower_bound,upper_bound)
113
+ data = data[(data[col] >= lower_bound) & (data[col] <= upper_bound)]
114
+ print('state: ', data['state'].value_counts())
115
+
116
+
117
+ st.subheader("3] Retard des locations")
118
+
119
+ if st.checkbox('Montrer uniquement les voitures rendues en retard', value=True):
120
+ mini = 0
121
+ df = data[data['delay_at_checkout_in_minutes']>mini]
122
+
123
+ else:
124
+ df = data
125
+ mini = int(df['delay_at_checkout_in_minutes'].min())
126
+
127
+ trsh = int(df['delay_at_checkout_in_minutes'].max())
128
+ seuil = st.slider("Choisir le temps de retard en minute", mini, int(df['delay_at_checkout_in_minutes'].max()), int(trsh*0.2))
129
+ maxi = int(df['delay_at_checkout_in_minutes'].max())
130
+
131
+ # seuil = st.slider("Choose the minute threshold!", 0, trsh, int(trsh*0.1))
132
+
133
+ move_upper_mask = df['delay_at_checkout_in_minutes']<seuil
134
+ lower_mask = df['delay_at_checkout_in_minutes']>mini
135
+ global_mask = move_upper_mask & lower_mask
136
+ number_of_rent = len(df[global_mask])
137
+ part_of_rent = 100 * len(df[move_upper_mask]) / len(df)
138
+
139
+ fig_px = px.histogram(df, color='checkin_type', x='delay_at_checkout_in_minutes')
140
+ fig = go.Figure(fig_px)
141
+
142
+ x = seuil
143
+
144
+ fig.add_shape(
145
+ type="line",
146
+ x0=x, x1=x, y0=0, y1=1,
147
+ line=dict(color="Green", width=2, dash="dash"),
148
+ xref='x', yref='paper'
149
+ )
150
+
151
+ fig.add_shape(
152
+ type="rect",
153
+ x0=mini, x1=x, y0=0, y1=1,
154
+ fillcolor="Green",
155
+ opacity=0.2,
156
+ line_width=0,
157
+ xref='x', yref='paper'
158
+ )
159
+
160
+ fig.update_layout(
161
+ title="",
162
+ xaxis_title="Delay at Checkout in Minutes",
163
+ yaxis_title="Count"
164
+ )
165
+
166
+ fig.add_annotation(
167
+ x=(x+mini)/2,
168
+ y=0.8,
169
+ xref='x',
170
+ yref='paper',
171
+ text=f"{number_of_rent}",
172
+ showarrow=False,
173
+ font=dict(size=12, color="Green"),
174
+ )
175
+ fig.add_annotation(
176
+ x=(x+mini)/2,
177
+ y=0.9,
178
+ xref='x',
179
+ yref='paper',
180
+ text=f"{part_of_rent:.2f}%",
181
+ showarrow=False,
182
+ font=dict(size=16, color="Green"),
183
+ )
184
+
185
+
186
+ fig.add_shape(
187
+ type="rect",
188
+ x0=x, x1=maxi, y0=0, y1=1,
189
+ fillcolor="Red",
190
+ opacity=0.2,
191
+ line_width=0,
192
+ xref='x', yref='paper'
193
+ )
194
+
195
+ fig.add_annotation(
196
+ x=(maxi+x)/2,
197
+ y=0.8,
198
+ xref='x',
199
+ yref='paper',
200
+ text=f"{len(df)-number_of_rent}",
201
+ showarrow=False,
202
+ font=dict(size=12, color="Red"),
203
+ )
204
+ fig.add_annotation(
205
+ x=(maxi+x)/2,
206
+ y=0.9,
207
+ xref='x',
208
+ yref='paper',
209
+ text=f"{100-part_of_rent:.2f}%",
210
+ showarrow=False,
211
+ font=dict(size=16, color="Red"),
212
+ )
213
+
214
+
215
+ st.plotly_chart(fig)
216
+
217
+ st.subheader("4] Impact du retard sur les conducteurs suivant")
218
+
219
+
220
+ df_late_impact = df[df['previous_ended_rental_id'].notna()]
221
+
222
+ if st.checkbox('Données brutes'):
223
+ st.write(df_late_impact)
224
+
225
+
226
+ fig_px = px.histogram(df_late_impact, color='checkin_type', x='time_delta_with_previous_rental_in_minutes', nbins=35)
227
+ fig = go.Figure(fig_px)
228
+
229
+ fig.update_layout(
230
+ title="",
231
+ xaxis_title="Retard en minutes",
232
+ yaxis_title="Nombre"
233
+ )
234
+
235
+ st.plotly_chart(fig)
236
+
237
+ car_brands = ["Citroën", "Peugeot", "PGO", "Renault", "Audi", "BMW", "other", "Mercedes", "Opel", "Volkswagen", "Ferrari", "Maserati", "Mitsubishi", "Nissan", "SEAT", "Subaru", "Toyota"]
238
+ fuel_types = ["diesel", "petrol", "hybrid_petrol", "electro"]
239
+ paint_colors = ["black", "grey", "white", "red", "silver", "blue", "orange", "beige", "brown", "green"]
240
+ car_types = ["convertible", "coupe", "estate", "hatchback", "sedan", "subcompact", "suv", "van"]
241
+
242
+ st.subheader("5] API de prédiction du prix optimal pour les voitures GetAround")
243
+
244
+ col1, col2, col3 = st.columns(3)
245
+
246
+ with col1:
247
+ marque = st.selectbox("Marque", car_brands, index=3)
248
+ kilometrage = st.number_input("Kilométrage", min_value=0, step=1000, value=10000)
249
+ puissance_moteur = st.number_input("Puissance du Moteur (HP)", min_value=0, step=10, value=100)
250
+
251
+ with col2:
252
+ carburant = st.selectbox("Type de Carburant", fuel_types, index=0)
253
+ couleur_peinture = st.selectbox("Couleur de la Peinture", paint_colors, index=0)
254
+ type_voiture = st.selectbox("Type de Voiture", car_types, index=0)
255
+
256
+ with col3:
257
+ parking_prive_disponible = st.checkbox("Parking Privé", value=True)
258
+ gps_disponible = st.checkbox("GPS Disponible", value=True)
259
+ climatisation_disponible = st.checkbox("Climatisation", value=True)
260
+ voiture_automatique = st.checkbox("Voiture Automatique", value=False)
261
+ getaround_connect_disponible = st.checkbox("GetAround Connect", value=True)
262
+ regulateur_vitesse_disponible = st.checkbox("Régulateur de Vitesse", value=True)
263
+ pneus_hiver = st.checkbox("Pneus Hiver", value=False)
264
+
265
+ url = "https://huggingface.co/spaces/deschamps-g/getaroundapi"
266
+
267
+ if st.button("Prédire le prix optimal de la voiture"):
268
+ input_data = {
269
+ "brand": marque,
270
+ "mileage": kilometrage,
271
+ "engine_power": puissance_moteur,
272
+ "fuel": carburant,
273
+ "paint_color": couleur_peinture,
274
+ "car_type": type_voiture,
275
+ "private_parking_available": parking_prive_disponible,
276
+ "has_gps": gps_disponible,
277
+ "has_air_conditioning": climatisation_disponible,
278
+ "automatic_car": voiture_automatique,
279
+ "has_getaround_connect": getaround_connect_disponible,
280
+ "has_speed_regulator": regulateur_vitesse_disponible,
281
+ "winter_tires": pneus_hiver
282
+ }
283
+
284
+ response = requests.post(url, params=input_data)
285
+
286
+ if response.status_code == 200:
287
+ result = response.json()
288
+ result = response.json()
289
+ prediction_value = round(result["prediction"], 2)
290
+ st.success(f"Prix de la location {prediction_value} $/jour")
291
+ else:
292
+ st.error(f"Erreur: {response.status_code}")
293
+ st.write(response.text)
294
+
295
+
296
+ st.markdown("""
297
+ <br>
298
+
299
+ <br>
300
+
301
+ """, unsafe_allow_html=True)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ pandas
3
+ plotly
4
+ numpy
5
+ openpyxl