perezcatriel commited on
Commit
ea3ea26
·
1 Parent(s): 83203a0
ML/geocoding/.env ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ API_KEY='AIzaSyAaqCt-qi-w7APxSjFXRgR3M5Z23Uj6NOE'
2
+ BASE_URL='https://maps.googleapis.com/maps/api/geocode/json'
ML/geocoding/app.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import folium
4
+ import matplotlib.pyplot as plt
5
+ import requests
6
+ import streamlit as st
7
+ from dotenv import load_dotenv
8
+ from sklearn.cluster import KMeans
9
+ from streamlit_folium import folium_static
10
+
11
+ load_dotenv()
12
+
13
+ st.set_page_config(layout='wide') # Para usar todo el ancho de la página
14
+
15
+ API_KEY = os.getenv('API_KEY')
16
+ BASE_URL = os.getenv('BASE_URL')
17
+
18
+
19
+ def geocode_address(address):
20
+ api_key = API_KEY
21
+ base_url = BASE_URL
22
+ params = {
23
+ 'address': address,
24
+ 'key': api_key
25
+ }
26
+
27
+ try:
28
+ response = requests.get(base_url, params=params)
29
+ data = response.json()
30
+
31
+ if data['status'] == 'OK' and len(data['results']) > 0:
32
+ location = data['results'][0]['geometry']['location']
33
+ latitude = location['lat']
34
+ longitude = location['lng']
35
+
36
+ return latitude, longitude
37
+ else:
38
+ st.error(
39
+ 'No se encontraron resultados para la dirección especificada.'
40
+ )
41
+ except requests.exceptions.RequestException as e:
42
+ st.error('Error en la solicitud:', e)
43
+
44
+
45
+ direcciones = [
46
+ 'San Martín y Garibaldi',
47
+ 'Avenida Emilio Civit s/n',
48
+ 'Parque General San Martín',
49
+ 'Calle Sarmiento, entre las calles Patricias Mendocinas y Garibaldi',
50
+ 'Calle Belgrano y España',
51
+ 'Calle Las Heras 50',
52
+ 'Plaza Independencia',
53
+ 'Avenida España y Costanera',
54
+ 'Calle 9 de Julio 1228',
55
+ 'Calle Chile 1754',
56
+ 'Avenida Arístides Villanueva',
57
+ 'Avenida Emilio Civit y España',
58
+ 'Calle Chile y Avenida Colón',
59
+ 'Calle Emilio Civit y Avenida San Martín',
60
+ 'Acceso Este y Avenida San Francisco de Asís',
61
+ 'Calle San Martín y Avellaneda',
62
+ 'Plaza Pedro del Castillo',
63
+ 'Calle San Martín y Avenida España',
64
+ 'Calle Emilio Civit y Avenida San Martín',
65
+ 'Avenida España',
66
+ 'Calle Avellaneda y Patricias Mendocinas',
67
+ 'Parque General San Martín',
68
+ 'Ruta Nacional 7',
69
+ 'Avenida Costanera y calle Peltier',
70
+ 'Calle Montecaseros 2625',
71
+ 'Calle Francisco Delgado 1220',
72
+ 'Ruta Provincial 86, s/n',
73
+ 'Ruta 15, km 23',
74
+ 'Calle San Martín 2044',
75
+ 'Ruta 7 y Acceso Sur'
76
+ ]
77
+
78
+ coordenadas = []
79
+ for direccion in direcciones:
80
+ resultado = geocode_address(direccion + ', Capital, Mendoza, Argentina')
81
+ if resultado:
82
+ coordenadas.append(resultado)
83
+ else:
84
+ coordenadas.append((None, None))
85
+
86
+ max_k = len(coordenadas)
87
+ inertias = []
88
+ for k in range(2, max_k + 1):
89
+ modelo = KMeans(n_clusters=k, random_state=42)
90
+ modelo.fit(coordenadas)
91
+ inertias.append(modelo.inertia_)
92
+
93
+ # Titulo
94
+
95
+ # Ajustar el tamaño del gráfico del codo
96
+ col1, col2, col3 = st.columns(3)
97
+
98
+ with col2:
99
+ col2.title('Clientes por Zonas')
100
+
101
+ fig, ax = plt.subplots(figsize=(6, 4))
102
+ ax.plot(range(2, max_k + 1), inertias, marker='o')
103
+ ax.set_xlabel('Número de zonas (k)')
104
+ ax.set_ylabel('Inercia')
105
+ ax.set_title('Método del Codo')
106
+ st.pyplot(fig)
107
+
108
+ k_optimo = st.number_input(
109
+ "Ingrese el valor óptimo de k según el gráfico:", min_value=2,
110
+ max_value=max_k, step=1
111
+ )
112
+
113
+ modelo = KMeans(n_clusters=k_optimo, random_state=42)
114
+ modelo.fit(coordenadas)
115
+
116
+ etiquetas = modelo.labels_
117
+ num_zonas = len(set(etiquetas))
118
+
119
+ zonas = {}
120
+ for i, etiqueta in enumerate(etiquetas):
121
+ if etiqueta not in zonas:
122
+ zonas[etiqueta] = []
123
+ zonas[etiqueta].append(direcciones[i])
124
+
125
+ # Crear el mapa centrado en la primera coordenada
126
+ primer_coordenada = coordenadas[0]
127
+ mapa = folium.Map(location=primer_coordenada, zoom_start=15)
128
+
129
+ colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred',
130
+ 'beige', 'darkblue', 'darkgreen', 'cadetblue',
131
+ 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray',
132
+ 'black', 'lightgray'] # Colores disponibles en Folium
133
+
134
+ for i, coordenada in enumerate(coordenadas):
135
+ zona = etiquetas[i] + 1
136
+ color = colors[zona % len(colors)]
137
+ if coordenada != (None, None):
138
+ folium.Marker(
139
+ location=coordenada, popup=f'Zona: {zona}',
140
+ icon=folium.Icon(color=color)
141
+ ).add_to(mapa)
142
+
143
+ # Mostrar el mapa y la leyenda en Streamlit en dos columnas
144
+ col1, col2, col3 = st.columns(3)
145
+ with col1:
146
+ folium_static(mapa, width=800, height=600)
147
+ with col3:
148
+ # Zonas ordenadas de forma descendente
149
+ for zona, direcciones_zona in sorted(zonas.items(), reverse=False):
150
+ st.markdown(
151
+ f"<div style='background-color:gray;'><span style='color:black;font-weight:bold;font-size:18px'>**ZONA"
152
+ f" {zona + 1}:**</span></div>",
153
+ unsafe_allow_html=True
154
+ )
155
+ for direccion in direcciones_zona:
156
+ st.markdown(f"<div>- {direccion}</div>", unsafe_allow_html=True)
157
+ st.markdown("<hr>", unsafe_allow_html=True)
ML/geocoding/doctest.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import janitor
2
+ import pandas as pd
3
+
4
+ diabetes_df = pd.read_csv("https://nrvis.com/data/mldata/pima-indians-diabetes.csv", names=['pregnancies', 'glucose', 'blood_pressurte', 'skin_thinckness', 'insulin', 'bmi', 'diabetes_pedigree_function', 'age', 'outcome'])
5
+ print(diabetes_df.info())
ML/geocoding/mapa.html ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+
5
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
6
+
7
+ <script>
8
+ L_NO_TOUCH = false;
9
+ L_DISABLE_3D = false;
10
+ </script>
11
+
12
+ <style>html, body {width: 100%;height: 100%;margin: 0;padding: 0;}</style>
13
+ <style>#map {position:absolute;top:0;bottom:0;right:0;left:0;}</style>
14
+ <script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.js"></script>
15
+ <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
17
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.js"></script>
18
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.3/dist/leaflet.css"/>
19
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css"/>
20
+ <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/>
21
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.0/css/all.min.css"/>
22
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Leaflet.awesome-markers/2.0.2/leaflet.awesome-markers.css"/>
23
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/python-visualization/folium/folium/templates/leaflet.awesome.rotate.min.css"/>
24
+
25
+ <meta name="viewport" content="width=device-width,
26
+ initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
27
+ <style>
28
+ #map_a1f3ad7074dad87fc12508baa541fc65 {
29
+ position: relative;
30
+ width: 100.0%;
31
+ height: 100.0%;
32
+ left: 0.0%;
33
+ top: 0.0%;
34
+ }
35
+ .leaflet-container { font-size: 1rem; }
36
+ </style>
37
+
38
+ </head>
39
+ <body>
40
+
41
+
42
+ <div class="folium-map" id="map_a1f3ad7074dad87fc12508baa541fc65" ></div>
43
+
44
+ </body>
45
+ <script>
46
+
47
+
48
+ var map_a1f3ad7074dad87fc12508baa541fc65 = L.map(
49
+ "map_a1f3ad7074dad87fc12508baa541fc65",
50
+ {
51
+ center: [-31.2468127, -64.4703813],
52
+ crs: L.CRS.EPSG3857,
53
+ zoom: 15,
54
+ zoomControl: true,
55
+ preferCanvas: false,
56
+ }
57
+ );
58
+
59
+
60
+
61
+
62
+
63
+ var tile_layer_d9d2b3f43262cdc24dcd2c54eeebb088 = L.tileLayer(
64
+ "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
65
+ {"attribution": "Data by \u0026copy; \u003ca target=\"_blank\" href=\"http://openstreetmap.org\"\u003eOpenStreetMap\u003c/a\u003e, under \u003ca target=\"_blank\" href=\"http://www.openstreetmap.org/copyright\"\u003eODbL\u003c/a\u003e.", "detectRetina": false, "maxNativeZoom": 18, "maxZoom": 18, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
66
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
67
+
68
+
69
+ var marker_64957d9a580d2f09d6b28627d2374f19 = L.marker(
70
+ [-31.2468127, -64.4703813],
71
+ {}
72
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
73
+
74
+
75
+ var icon_e7fcc95ead3ff14f2e41fbbd6da350af = L.AwesomeMarkers.icon(
76
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "green", "prefix": "glyphicon"}
77
+ );
78
+ marker_64957d9a580d2f09d6b28627d2374f19.setIcon(icon_e7fcc95ead3ff14f2e41fbbd6da350af);
79
+
80
+
81
+ var popup_bf3d0b061120e3d729bed354e930e4df = L.popup({"maxWidth": "100%"});
82
+
83
+
84
+
85
+ var html_bd14c223170ed15e88a0f653d228e0e2 = $(`<div id="html_bd14c223170ed15e88a0f653d228e0e2" style="width: 100.0%; height: 100.0%;">Zona: 2</div>`)[0];
86
+ popup_bf3d0b061120e3d729bed354e930e4df.setContent(html_bd14c223170ed15e88a0f653d228e0e2);
87
+
88
+
89
+
90
+ marker_64957d9a580d2f09d6b28627d2374f19.bindPopup(popup_bf3d0b061120e3d729bed354e930e4df)
91
+ ;
92
+
93
+
94
+
95
+
96
+ var marker_3e649aefb9e78244fb39c588fd9a3ac9 = L.marker(
97
+ [-31.2376351, -64.4633182],
98
+ {}
99
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
100
+
101
+
102
+ var icon_c2e37e415e755d5ae2fb5d6744152223 = L.AwesomeMarkers.icon(
103
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "orange", "prefix": "glyphicon"}
104
+ );
105
+ marker_3e649aefb9e78244fb39c588fd9a3ac9.setIcon(icon_c2e37e415e755d5ae2fb5d6744152223);
106
+
107
+
108
+ var popup_07653847e4a06ae31938ebcb8d2eca37 = L.popup({"maxWidth": "100%"});
109
+
110
+
111
+
112
+ var html_21e5747412cad3612aafc34fd6b3be25 = $(`<div id="html_21e5747412cad3612aafc34fd6b3be25" style="width: 100.0%; height: 100.0%;">Zona: 4</div>`)[0];
113
+ popup_07653847e4a06ae31938ebcb8d2eca37.setContent(html_21e5747412cad3612aafc34fd6b3be25);
114
+
115
+
116
+
117
+ marker_3e649aefb9e78244fb39c588fd9a3ac9.bindPopup(popup_07653847e4a06ae31938ebcb8d2eca37)
118
+ ;
119
+
120
+
121
+
122
+
123
+ var marker_e13999e64912723800ac3a97727dabd4 = L.marker(
124
+ [-31.2389973, -64.46556919999999],
125
+ {}
126
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
127
+
128
+
129
+ var icon_423d8e108dfccb44e2e748ecfbf23787 = L.AwesomeMarkers.icon(
130
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "orange", "prefix": "glyphicon"}
131
+ );
132
+ marker_e13999e64912723800ac3a97727dabd4.setIcon(icon_423d8e108dfccb44e2e748ecfbf23787);
133
+
134
+
135
+ var popup_6b92830b169df9aabdb773716653a875 = L.popup({"maxWidth": "100%"});
136
+
137
+
138
+
139
+ var html_5b7bdc07ff7b072d83d0e5d219eeb336 = $(`<div id="html_5b7bdc07ff7b072d83d0e5d219eeb336" style="width: 100.0%; height: 100.0%;">Zona: 4</div>`)[0];
140
+ popup_6b92830b169df9aabdb773716653a875.setContent(html_5b7bdc07ff7b072d83d0e5d219eeb336);
141
+
142
+
143
+
144
+ marker_e13999e64912723800ac3a97727dabd4.bindPopup(popup_6b92830b169df9aabdb773716653a875)
145
+ ;
146
+
147
+
148
+
149
+
150
+ var marker_b93dbbfe159140629cbf332f09d29fb3 = L.marker(
151
+ [-31.2461472, -64.4675932],
152
+ {}
153
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
154
+
155
+
156
+ var icon_f3eff6f0f41d10a6d2f8b923fdd1ef19 = L.AwesomeMarkers.icon(
157
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "green", "prefix": "glyphicon"}
158
+ );
159
+ marker_b93dbbfe159140629cbf332f09d29fb3.setIcon(icon_f3eff6f0f41d10a6d2f8b923fdd1ef19);
160
+
161
+
162
+ var popup_a842edfd2578ea5cc15a45349fe70352 = L.popup({"maxWidth": "100%"});
163
+
164
+
165
+
166
+ var html_5952226ea8ba9fb25833269dddf881d7 = $(`<div id="html_5952226ea8ba9fb25833269dddf881d7" style="width: 100.0%; height: 100.0%;">Zona: 2</div>`)[0];
167
+ popup_a842edfd2578ea5cc15a45349fe70352.setContent(html_5952226ea8ba9fb25833269dddf881d7);
168
+
169
+
170
+
171
+ marker_b93dbbfe159140629cbf332f09d29fb3.bindPopup(popup_a842edfd2578ea5cc15a45349fe70352)
172
+ ;
173
+
174
+
175
+
176
+
177
+ var marker_5fb01bff2859eb66072623e7ad9770bd = L.marker(
178
+ [-31.239973, -64.4644586],
179
+ {}
180
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
181
+
182
+
183
+ var icon_6c7815e67ee4acfcbdfe1f852f3834a2 = L.AwesomeMarkers.icon(
184
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "orange", "prefix": "glyphicon"}
185
+ );
186
+ marker_5fb01bff2859eb66072623e7ad9770bd.setIcon(icon_6c7815e67ee4acfcbdfe1f852f3834a2);
187
+
188
+
189
+ var popup_d7de584cc05fc008402fa0c6f109995d = L.popup({"maxWidth": "100%"});
190
+
191
+
192
+
193
+ var html_29546a4b2f178012f1a69ad8339ef433 = $(`<div id="html_29546a4b2f178012f1a69ad8339ef433" style="width: 100.0%; height: 100.0%;">Zona: 4</div>`)[0];
194
+ popup_d7de584cc05fc008402fa0c6f109995d.setContent(html_29546a4b2f178012f1a69ad8339ef433);
195
+
196
+
197
+
198
+ marker_5fb01bff2859eb66072623e7ad9770bd.bindPopup(popup_d7de584cc05fc008402fa0c6f109995d)
199
+ ;
200
+
201
+
202
+
203
+
204
+ var marker_660272a8e6a9031a3cb8324214221a39 = L.marker(
205
+ [-31.2244469, -64.4678538],
206
+ {}
207
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
208
+
209
+
210
+ var icon_7a32c7a49fceb55b4804a7eab8ce3a0b = L.AwesomeMarkers.icon(
211
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "purple", "prefix": "glyphicon"}
212
+ );
213
+ marker_660272a8e6a9031a3cb8324214221a39.setIcon(icon_7a32c7a49fceb55b4804a7eab8ce3a0b);
214
+
215
+
216
+ var popup_b4dab0d2a4e5ddb561507ab22762096b = L.popup({"maxWidth": "100%"});
217
+
218
+
219
+
220
+ var html_3d3402b57f1c4c8f3fd8e687d4496159 = $(`<div id="html_3d3402b57f1c4c8f3fd8e687d4496159" style="width: 100.0%; height: 100.0%;">Zona: 3</div>`)[0];
221
+ popup_b4dab0d2a4e5ddb561507ab22762096b.setContent(html_3d3402b57f1c4c8f3fd8e687d4496159);
222
+
223
+
224
+
225
+ marker_660272a8e6a9031a3cb8324214221a39.bindPopup(popup_b4dab0d2a4e5ddb561507ab22762096b)
226
+ ;
227
+
228
+
229
+
230
+
231
+ var marker_8a9a6753c3e9bf0c4e22f5d6e443c52c = L.marker(
232
+ [-31.2356614, -64.4640941],
233
+ {}
234
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
235
+
236
+
237
+ var icon_09f089bd0dcec99bef389d0fab73810d = L.AwesomeMarkers.icon(
238
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "orange", "prefix": "glyphicon"}
239
+ );
240
+ marker_8a9a6753c3e9bf0c4e22f5d6e443c52c.setIcon(icon_09f089bd0dcec99bef389d0fab73810d);
241
+
242
+
243
+ var popup_bf8c1388893ad7e8c5f5a5c5c1012739 = L.popup({"maxWidth": "100%"});
244
+
245
+
246
+
247
+ var html_fd831a8eea231f4b940c925bce0f77b2 = $(`<div id="html_fd831a8eea231f4b940c925bce0f77b2" style="width: 100.0%; height: 100.0%;">Zona: 4</div>`)[0];
248
+ popup_bf8c1388893ad7e8c5f5a5c5c1012739.setContent(html_fd831a8eea231f4b940c925bce0f77b2);
249
+
250
+
251
+
252
+ marker_8a9a6753c3e9bf0c4e22f5d6e443c52c.bindPopup(popup_bf8c1388893ad7e8c5f5a5c5c1012739)
253
+ ;
254
+
255
+
256
+
257
+
258
+ var marker_19a21bb4d7758eed979556e650fd9850 = L.marker(
259
+ [-31.2388731, -64.4632158],
260
+ {}
261
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
262
+
263
+
264
+ var icon_6aa5a3f73b9121334c3529cb0478ee56 = L.AwesomeMarkers.icon(
265
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "orange", "prefix": "glyphicon"}
266
+ );
267
+ marker_19a21bb4d7758eed979556e650fd9850.setIcon(icon_6aa5a3f73b9121334c3529cb0478ee56);
268
+
269
+
270
+ var popup_951f0a1581569f022e99e6aa8e9d338c = L.popup({"maxWidth": "100%"});
271
+
272
+
273
+
274
+ var html_aacefb7498fe48e7b5fb3b63b9f7d7b9 = $(`<div id="html_aacefb7498fe48e7b5fb3b63b9f7d7b9" style="width: 100.0%; height: 100.0%;">Zona: 4</div>`)[0];
275
+ popup_951f0a1581569f022e99e6aa8e9d338c.setContent(html_aacefb7498fe48e7b5fb3b63b9f7d7b9);
276
+
277
+
278
+
279
+ marker_19a21bb4d7758eed979556e650fd9850.bindPopup(popup_951f0a1581569f022e99e6aa8e9d338c)
280
+ ;
281
+
282
+
283
+
284
+
285
+ var marker_feaf44d2278fe7179ccd0d5e2eb15adc = L.marker(
286
+ [-31.2385765, -64.4657421],
287
+ {}
288
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
289
+
290
+
291
+ var icon_8f40d2ca12bda04ade22e98328cdf5df = L.AwesomeMarkers.icon(
292
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "orange", "prefix": "glyphicon"}
293
+ );
294
+ marker_feaf44d2278fe7179ccd0d5e2eb15adc.setIcon(icon_8f40d2ca12bda04ade22e98328cdf5df);
295
+
296
+
297
+ var popup_8be21ff1f811e905ae07dd9c3e1cb918 = L.popup({"maxWidth": "100%"});
298
+
299
+
300
+
301
+ var html_91d720565690b9c0803d95e567d3a4cb = $(`<div id="html_91d720565690b9c0803d95e567d3a4cb" style="width: 100.0%; height: 100.0%;">Zona: 4</div>`)[0];
302
+ popup_8be21ff1f811e905ae07dd9c3e1cb918.setContent(html_91d720565690b9c0803d95e567d3a4cb);
303
+
304
+
305
+
306
+ marker_feaf44d2278fe7179ccd0d5e2eb15adc.bindPopup(popup_8be21ff1f811e905ae07dd9c3e1cb918)
307
+ ;
308
+
309
+
310
+
311
+
312
+ var marker_42ca96bf651128ed0c4cd9b5123810e0 = L.marker(
313
+ [-31.2475221, -64.4670759],
314
+ {}
315
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
316
+
317
+
318
+ var icon_b01aa13d507a66bc9c2635134a99fa5f = L.AwesomeMarkers.icon(
319
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "green", "prefix": "glyphicon"}
320
+ );
321
+ marker_42ca96bf651128ed0c4cd9b5123810e0.setIcon(icon_b01aa13d507a66bc9c2635134a99fa5f);
322
+
323
+
324
+ var popup_e72e5359945fbb012812026e5c1ba4c2 = L.popup({"maxWidth": "100%"});
325
+
326
+
327
+
328
+ var html_da8d62fbe3e6f3578064566e4a1cff1b = $(`<div id="html_da8d62fbe3e6f3578064566e4a1cff1b" style="width: 100.0%; height: 100.0%;">Zona: 2</div>`)[0];
329
+ popup_e72e5359945fbb012812026e5c1ba4c2.setContent(html_da8d62fbe3e6f3578064566e4a1cff1b);
330
+
331
+
332
+
333
+ marker_42ca96bf651128ed0c4cd9b5123810e0.bindPopup(popup_e72e5359945fbb012812026e5c1ba4c2)
334
+ ;
335
+
336
+
337
+
338
+
339
+ var marker_5dabd99b029782f8b9cd78ac26d62093 = L.marker(
340
+ [-31.234152, -64.4582696],
341
+ {}
342
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
343
+
344
+
345
+ var icon_877898bc86e5c023c519334e6433aed4 = L.AwesomeMarkers.icon(
346
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "blue", "prefix": "glyphicon"}
347
+ );
348
+ marker_5dabd99b029782f8b9cd78ac26d62093.setIcon(icon_877898bc86e5c023c519334e6433aed4);
349
+
350
+
351
+ var popup_f4424169d52f5561070611bccf7ec318 = L.popup({"maxWidth": "100%"});
352
+
353
+
354
+
355
+ var html_9ceeb9fa4dd64455bee680a9253ce92e = $(`<div id="html_9ceeb9fa4dd64455bee680a9253ce92e" style="width: 100.0%; height: 100.0%;">Zona: 1</div>`)[0];
356
+ popup_f4424169d52f5561070611bccf7ec318.setContent(html_9ceeb9fa4dd64455bee680a9253ce92e);
357
+
358
+
359
+
360
+ marker_5dabd99b029782f8b9cd78ac26d62093.bindPopup(popup_f4424169d52f5561070611bccf7ec318)
361
+ ;
362
+
363
+
364
+
365
+
366
+ var marker_c2f9f86bff3637c2e4c7c432201c3296 = L.marker(
367
+ [-31.234662, -64.4575523],
368
+ {}
369
+ ).addTo(map_a1f3ad7074dad87fc12508baa541fc65);
370
+
371
+
372
+ var icon_1b34080c3954afb91023ae98403ccbc2 = L.AwesomeMarkers.icon(
373
+ {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "blue", "prefix": "glyphicon"}
374
+ );
375
+ marker_c2f9f86bff3637c2e4c7c432201c3296.setIcon(icon_1b34080c3954afb91023ae98403ccbc2);
376
+
377
+
378
+ var popup_273c92c917e5b50ca34588b1aaec4851 = L.popup({"maxWidth": "100%"});
379
+
380
+
381
+
382
+ var html_be5f558e220bb41bf1ae1aa7efd96f7f = $(`<div id="html_be5f558e220bb41bf1ae1aa7efd96f7f" style="width: 100.0%; height: 100.0%;">Zona: 1</div>`)[0];
383
+ popup_273c92c917e5b50ca34588b1aaec4851.setContent(html_be5f558e220bb41bf1ae1aa7efd96f7f);
384
+
385
+
386
+
387
+ marker_c2f9f86bff3637c2e4c7c432201c3296.bindPopup(popup_273c92c917e5b50ca34588b1aaec4851)
388
+ ;
389
+
390
+
391
+
392
+ </script>
393
+ </html>
ML/geocoding/modelo.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import os
3
+ import requests
4
+ from dotenv import load_dotenv
5
+ import folium
6
+ import streamlit as st
7
+ import joblib
8
+ from sklearn.cluster import KMeans
9
+ import numpy as np
10
+ import matplotlib.pyplot as plt
11
+
12
+ load_dotenv()
13
+
14
+ API_KEY = os.getenv('API_KEY')
15
+ BASE_URL = os.getenv('BASE_URL')
16
+
17
+ def geocode_address(address):
18
+ # Aquí debes insertar tu clave de API de Google Maps
19
+ api_key = API_KEY
20
+
21
+ # URL base de la API de Geocodificación de Google Maps
22
+ base_url = BASE_URL
23
+
24
+ # Parámetros de la solicitud
25
+ params = {
26
+ 'address': address,
27
+ 'key': api_key
28
+ }
29
+
30
+ try:
31
+ # Realizar la solicitud a la API de Geocodificación
32
+ response = requests.get(base_url, params=params)
33
+ data = response.json()
34
+
35
+ if data['status'] == 'OK' and len(data['results']) > 0:
36
+ # Obtener las coordenadas geográficas de la primera coincidencia
37
+ location = data['results'][0]['geometry']['location']
38
+ latitude = location['lat']
39
+ longitude = location['lng']
40
+
41
+ return latitude, longitude
42
+ else:
43
+ print('No se encontraron resultados para la dirección especificada.')
44
+ except requests.exceptions.RequestException as e:
45
+ print('Error en la solicitud:', e)
46
+
47
+
48
+ # Direcciones ficticias en Cosquín, Córdoba, Argentina
49
+ direcciones = [
50
+ 'San Martín 123',
51
+ 'Tucumán 456',
52
+ 'Catamarca 789',
53
+ 'Perón 1321',
54
+ 'Corrientes 654',
55
+ 'Laurencena 877',
56
+ 'San Martín 234',
57
+ 'Tucumán 567',
58
+ 'Catamarca 890',
59
+ 'San Martin 1432',
60
+ 'Avenida parana 10',
61
+ 'Japon 23'
62
+ ]
63
+
64
+ # Obtener las coordenadas geográficas de cada dirección
65
+ coordenadas = []
66
+ for direccion in direcciones:
67
+ resultado = geocode_address(direccion + ', Cosquín, Córdoba, Argentina')
68
+ if resultado:
69
+ coordenadas.append(resultado)
70
+ else:
71
+ coordenadas.append((None, None))
72
+
73
+ # Calcular el número de zonas (k) utilizando el método del codo
74
+ max_k = len(coordenadas)
75
+ inertias = []
76
+ for k in range(2, max_k+1):
77
+ modelo = KMeans(n_clusters=k, random_state=42)
78
+ modelo.fit(coordenadas)
79
+ inertias.append(modelo.inertia_)
80
+
81
+ # Graficar las inercias en función de k
82
+ plt.plot(range(2, max_k+1), inertias, marker='o')
83
+ plt.xlabel('Número de zonas (k)')
84
+ plt.ylabel('Inercia')
85
+ plt.title('Método del Codo')
86
+ plt.show()
87
+
88
+ # Elegir el valor de k óptimo
89
+ k_optimo = int(input("Ingrese el valor óptimo de k según el gráfico: "))
90
+
91
+ # Crear el modelo de K-Means con k_optimo zonas
92
+ modelo = KMeans(n_clusters=k_optimo, random_state=42)
93
+ modelo.fit(coordenadas)
94
+
95
+ # Obtener las etiquetas de las zonas
96
+ etiquetas = modelo.labels_
97
+
98
+ # Contar el número de zonas
99
+ num_zonas = len(set(etiquetas))
100
+
101
+ # Crear un diccionario para almacenar las direcciones por zona
102
+ zonas = {}
103
+ for i, etiqueta in enumerate(etiquetas):
104
+ if etiqueta not in zonas:
105
+ zonas[etiqueta] = []
106
+ zonas[etiqueta].append(direcciones[i])
107
+
108
+ # Mostrar las direcciones por zona
109
+ for zona, direcciones_zona in zonas.items():
110
+ print(f"Zona {zona + 1}:")
111
+ for direccion in direcciones_zona:
112
+ print(direccion)
113
+ print()
114
+
115
+ # Lista de colores predefinidos
116
+ colores = ['red', 'blue', 'green', 'purple', 'orange', 'gray', 'pink',
117
+ 'cyan', 'yellow', 'brown', 'black', 'white', 'violet']
118
+
119
+ # Crear un mapa centrado en la primera coordenada
120
+ primer_coordenada = coordenadas[0]
121
+ mapa = folium.Map(location=primer_coordenada, zoom_start=15)
122
+
123
+ # Agregar marcadores para cada coordenada con su zona y color correspondiente
124
+ for i, coordenada in enumerate(coordenadas):
125
+ zona = etiquetas[i] + 1 # Sumar 1 para que las zonas se muestren como números a partir de 1
126
+ if coordenada != (None, None):
127
+ color = colores[zona % len(colores)] # Obtener el color correspondiente a la zona
128
+ folium.Marker(location=coordenada, popup=f'Zona: {zona}', icon=folium.Icon(color=color)).add_to(mapa)
129
+ else:
130
+ folium.Marker(location=coordenada, popup='Ubicación desconocida').add_to(mapa)
131
+
132
+ # Guardar el mapa como un archivo HTML
133
+ mapa.save('mapa.html')
134
+
135
+ # Abrir el archivo HTML en el navegador para visualizar el mapa
136
+ import webbrowser
137
+ webbrowser.open('mapa.html')
ML/geocoding/requirements.txt ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ altair==4.2.2
2
+ args==0.1.0
3
+ attrs==23.1.0
4
+ blinker==1.6.2
5
+ branca==0.6.0
6
+ cachetools==5.3.0
7
+ certifi==2023.5.7
8
+ charset-normalizer==3.1.0
9
+ click==8.1.3
10
+ clint==0.5.1
11
+ contourpy==1.0.7
12
+ coverage==7.2.5
13
+ cycler==0.11.0
14
+ decorator==5.1.1
15
+ entrypoints==0.4
16
+ folium==0.14.0
17
+ fonttools==4.39.4
18
+ gitdb==4.0.10
19
+ GitPython==3.1.31
20
+ idna==3.4
21
+ importlib-metadata==6.6.0
22
+ Jinja2==3.1.2
23
+ joblib==1.2.0
24
+ jsonschema==4.17.3
25
+ kiwisolver==1.4.4
26
+ mamba==0.11.2
27
+ markdown-it-py==2.2.0
28
+ MarkupSafe==2.1.2
29
+ matplotlib==3.7.1
30
+ mdurl==0.1.2
31
+ numpy==1.24.3
32
+ packaging==23.1
33
+ pandas==2.0.1
34
+ Pillow==9.5.0
35
+ plotly==5.14.1
36
+ protobuf==3.20.3
37
+ pyarrow==12.0.0
38
+ pydeck==0.8.1b0
39
+ Pygments==2.15.1
40
+ Pympler==1.0.1
41
+ pyparsing==3.0.9
42
+ pyrsistent==0.19.3
43
+ python-dateutil==2.8.2
44
+ python-dotenv==1.0.0
45
+ pytz==2023.3
46
+ requests==2.31.0
47
+ rich==13.3.5
48
+ scikit-learn==1.2.2
49
+ scipy==1.10.1
50
+ six==1.16.0
51
+ smmap==5.0.0
52
+ streamlit==1.22.0
53
+ streamlit-folium==0.11.1
54
+ tenacity==8.2.2
55
+ threadpoolctl==3.1.0
56
+ toml==0.10.2
57
+ toolz==0.12.0
58
+ tornado==6.3.2
59
+ typing_extensions==4.6.0
60
+ tzdata==2023.3
61
+ tzlocal==5.0.1
62
+ urllib3==2.0.2
63
+ validators==0.20.0
64
+ watchdog==3.0.0
65
+ zipp==3.15.0
__pycache__/boxplot_clientes.cpython-311.pyc ADDED
Binary file (2.13 kB). View file
 
__pycache__/top_5_clientes.cpython-311.pyc ADDED
Binary file (2.19 kB). View file
 
__pycache__/ventas_anuales_clientes.cpython-311.pyc ADDED
Binary file (1.55 kB). View file