Spaces:
Runtime error
Runtime error
Commit
·
9f5cca2
0
Parent(s):
Proyecto Lab-2 Primer Commit
Browse files- .gitignore +8 -0
- README.md +290 -0
- assets/styles.css +281 -0
- components/component_home.py +37 -0
- components/component_tab2.py +11 -0
- components/component_tab2_grafico.py +274 -0
- components/component_tab2_left.py +24 -0
- components/component_tab2_textos.py +160 -0
- components/component_tab3.py +34 -0
- components/component_tab3_barras.py +74 -0
- components/component_tab3_donuts.py +84 -0
- components/component_tab3_drop.py +33 -0
- components/component_tab3_tarjetas.py +36 -0
- components/component_tab4.py +14 -0
- components/component_tab4_donuts.py +87 -0
- components/component_tab4_left.py +54 -0
- components/component_tab4_mapa.py +119 -0
- components/component_tab4_retorna_texto.py +41 -0
- data/EDA_internet_rangos.parquet +0 -0
- data/EDA_internet_tecnologias.parquet +0 -0
- data/accesos_localidades_dash.parquet +0 -0
- data/data_tablero_dashboard.parquet +0 -0
- data/df_pie_tab2.parquet +0 -0
- data/internet_tab2.parquet +0 -0
- data/rangos_internet_graficos_tab2 copy.parquet +0 -0
- data/rangos_internet_graficos_tab2.parquet +0 -0
- data/rangos_localidades.parquet +0 -0
- data/tarjetas.parquet +0 -0
- data/tecnologias_internet_graficos_tab2 copy.parquet +0 -0
- data/tecnologias_internet_graficos_tab2.parquet +0 -0
- data/telefonia_fija_tab2.parquet +0 -0
- data/telefonia_movil_tab2.parquet +0 -0
- data/television_tab2.parquet +0 -0
- main.py +246 -0
- requirements.txt +6 -0
- utils/retorna_dfs_grfaicos_tab4.py +71 -0
.gitignore
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Excluir el entorno virtual de Python
|
| 2 |
+
venv/
|
| 3 |
+
|
| 4 |
+
# Excluir el archivo .flake8
|
| 5 |
+
.flake8
|
| 6 |
+
|
| 7 |
+
# Excluir todas las carpetas __pycache__
|
| 8 |
+
__pycache__/
|
README.md
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div style="text-align: center; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 10px 0;">
|
| 2 |
+
<h1 style="color: lightblue; font-size: 2em;">Proyecto Labs 2</h1>
|
| 3 |
+
</div>
|
| 4 |
+
|
| 5 |
+
## Descripción
|
| 6 |
+
|
| 7 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 8 |
+
Este proyecto se centra en un exhaustivo análisis del sector de las telecomunicaciones en Argentina, utilizando datos extraídos del Ente Nacional de Comunicaciones (ENACOM). Se a estudiado la evolución de los ingresos y la penetración de mercado en los sectores de Telefonía Fija, Telefonía Móvil, Internet y Televisión, a lo largo de la última década.</p>
|
| 9 |
+
|
| 10 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 11 |
+
EL análisis se profundiza especialmente en el sector de Internet, donde se examinó el comportamiento del mercado en relación con las tecnologías que brindan el servicio, tales como ADSL, WIRELESS, Fibra Óptica y Cable Modem, y las Velocidades Medias de Descargas, tanto a nivel Nacional como de Provincias.</p>
|
| 12 |
+
|
| 13 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 14 |
+
Para una mejor comprensión del comportamiento del sector se empleo el uso de dos(2) KPI's a nivel de Provincias y tres(3) Métricas Nacionales, todas ellas de seguimiento trimestral.</p>
|
| 15 |
+
|
| 16 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 17 |
+
Los KPI empleados fueron:</p>
|
| 18 |
+
|
| 19 |
+
- **Crecimiento Trimestral de 2% en el número de Accesos por cada 100 Hogares por Provincia**:
|
| 20 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 21 |
+
Donde el Objetivo para el siguiente Trimestre se fijará simplemente añadiendo un 2% a los accesos por cada 100 Hogares del trimestre actual. Y cuando lleguemos en el tiempo al siguiente trimestre, la Medición del cumplimiento de dicho objetivo sería de la siguiente manera:</p>
|
| 22 |
+
<br>
|
| 23 |
+
|
| 24 |
+
$$
|
| 25 |
+
\text{Cumplimiento KPI} = \left( \frac{\text{Acc 100 Hog Trim}}{\text{Objetivo KPI}} \right) \times 100
|
| 26 |
+
$$
|
| 27 |
+
|
| 28 |
+
<br>
|
| 29 |
+
<br>
|
| 30 |
+
- **Crecimiento Trimestral de 5% en la Velocidad Media de Bajada por Provincia**:
|
| 31 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 32 |
+
Donde el Objetivo para el siguiente Trimestre se fijará simplemente añadiendo un 5% a la velocidad del Trimestre actual. Y cuando lleguemos en el tiempo al siguiente trimestre, la Medición del cumplimiento de dicho objetivo sería de la siguiente manera:</p>
|
| 33 |
+
<br>
|
| 34 |
+
|
| 35 |
+
$$
|
| 36 |
+
\text{Cumplimiento KPI} = \left( \frac{\text{Vel Mbps Trim}}{\text{Objetivo KPI}} \right) \times 100
|
| 37 |
+
$$
|
| 38 |
+
|
| 39 |
+
<br>
|
| 40 |
+
<br>
|
| 41 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 42 |
+
Las Métricas utilizadas fueron:</p>
|
| 43 |
+
|
| 44 |
+
- **Variación Trimestral del número de Accesos por cada 100 Hogares en el País**:
|
| 45 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 46 |
+
El cálculo de la métrica se realiza de la siguiente manera:</p>
|
| 47 |
+
<br>
|
| 48 |
+
|
| 49 |
+
$$
|
| 50 |
+
\text{Var Accesos 100 Hog} = \left( \frac{\text{Accesos Trimestre}}{\text{Accesos Trimestre Anterior}} - 1 \right) \times 100
|
| 51 |
+
$$
|
| 52 |
+
|
| 53 |
+
<br>
|
| 54 |
+
<br>
|
| 55 |
+
- **Variación Trimestral de la Velocidad Media de Bajada en el País**:
|
| 56 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 57 |
+
El cálculo de la métrica se realiza de la siguiente manera:</p>
|
| 58 |
+
<br>
|
| 59 |
+
|
| 60 |
+
$$
|
| 61 |
+
\text{Var Mbps} = \left( \frac{\text{Vel Mbps Trim}}{\text{Vel Mbps Trim Anterior}} - 1 \right) \times 100
|
| 62 |
+
$$
|
| 63 |
+
|
| 64 |
+
<br>
|
| 65 |
+
<br>
|
| 66 |
+
- **Total de Accesos en el País**:
|
| 67 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 68 |
+
Simplemente se monitorea el <b>Total de Accesos en el país en el Trimestre en curso</b>
|
| 69 |
+
<br>
|
| 70 |
+
|
| 71 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 72 |
+
Para facilitar la comprensión y visualización de los datos, desarrollamos una herramienta interactiva utilizando Python y el framework Dash de la librería Plotly. Esta herramienta permite a los usuarios explorar los datos de manera intuitiva y obtener insights valiosos.</p><br>
|
| 73 |
+
<br>
|
| 74 |
+
<image src='assets/capture_tooltip.png'><br>
|
| 75 |
+
<br>
|
| 76 |
+
<image src='assets/capture_mapa_oportunidades.png'><br>
|
| 77 |
+
<br>
|
| 78 |
+
|
| 79 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 80 |
+
Previo al análisis, normalizamos los datos y creamos un modelo de datos en SQL (EDR) funcional para la empresa, que sirve como un data warehouse. Este modelo no solo organiza los datos de manera eficiente, sino que también está diseñado para soportar futuros estudios y análisis. EL EDR creado se puede observar en la siguiente Imagen<br></p>
|
| 81 |
+
<br>
|
| 82 |
+
|
| 83 |
+
<image src='noteboocks/assets/edr.png'>
|
| 84 |
+
|
| 85 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 86 |
+
Este proyecto no sdlo demuestra habilidades técnicas en análisis de datos y visualización, sino también una comprensión profunda del sector de telecomunicaciones y la capacidad de transformar datos complejos en información útil para la toma de decisiones estratégicas.</p>
|
| 87 |
+
|
| 88 |
+
## Tabla de contenido
|
| 89 |
+
|
| 90 |
+
1. [Descripción](#descripción)
|
| 91 |
+
1. [Enlaces](#enlaces)
|
| 92 |
+
1. [Instalación y Requisitos](#instalación-y-requisitos)
|
| 93 |
+
1. [Estructura del Proyecto](#estructura-del-proyecto)
|
| 94 |
+
1. [Uso y Ejecución](#uso-y-ejecución)
|
| 95 |
+
1. [Datos y Fuentes](#datos-y-fuentes)
|
| 96 |
+
1. [Metodología](#metodología)
|
| 97 |
+
1. [Conclusiones y Recomendaciones](#resultados-y-conclusiones)
|
| 98 |
+
1. [Autores](#autores)
|
| 99 |
+
|
| 100 |
+
## Enlaces
|
| 101 |
+
|
| 102 |
+
- **Enlace al repositorio**
|
| 103 |
+
- https://github.com/aliskairraul/Bootcamp-Henry-Proyecto-Lab_2.git
|
| 104 |
+
|
| 105 |
+
## Instalación y Requisitos
|
| 106 |
+
|
| 107 |
+
**Requisitos:**
|
| 108 |
+
|
| 109 |
+
- Requisitos para la app
|
| 110 |
+
|
| 111 |
+
- Python 3.10
|
| 112 |
+
- dash==2.16.1
|
| 113 |
+
- dash_daq==0.5.0
|
| 114 |
+
- pandas==2.2.2
|
| 115 |
+
- plotly==5.21.0
|
| 116 |
+
- polars==1.2.1
|
| 117 |
+
- pyarrow==17.0.0
|
| 118 |
+
|
| 119 |
+
- Requisitos para los Notebooks
|
| 120 |
+
- Python 3.10
|
| 121 |
+
- jupyter==1.1.1
|
| 122 |
+
- pandas==2.2.2
|
| 123 |
+
- polars==1.7.1
|
| 124 |
+
- plotly==5.24.1
|
| 125 |
+
- fastexcel==0.11.6
|
| 126 |
+
- duckdb==1.1.0
|
| 127 |
+
- pyarrow==17.0.0
|
| 128 |
+
- sqlalchemy==2.0.35
|
| 129 |
+
- PyMySQL==1.1.1
|
| 130 |
+
|
| 131 |
+
**Pasos de instalación:**
|
| 132 |
+
|
| 133 |
+
1. Clonar el repositorio: `git clone https://github.com/aliskairraul/Bootcamp-Henry-Proyecto-Lab_2.git`
|
| 134 |
+
2. Partamos del echo de que esto debe tratarse como 2 sub-proyectos por separado (un Análisis y una Aplicación realizada en Dash). Cree dos carpetas dentro de su ordenador
|
| 135 |
+
|
| 136 |
+
- Una Carpeta va todo lo referente al análisis y el modelo (Allí va a copiar sólo la Carpeta `notebooks` de este repositorio)
|
| 137 |
+
- En la otra Carpeta tendrá todo lo referente a la App de Dash (Allí va `TODO el Repositorio, excepto la Carpeta notebooks`)
|
| 138 |
+
|
| 139 |
+
4. Crear un entorno virtual en cada carpeta: `python3.10 -m venv nombre_del_entorno`
|
| 140 |
+
5. El Archivo `requirements.txt` en la raiz del proyecto son las dependencias para la App realizada en Dash y es el que debe usar para la carpeta en que tenga dicha App
|
| 141 |
+
6. El Archivo `requirements.txt` que se encuentra dentro de la carpeta `notebooks` es el que debe usar para instalar las dependencias del análisis
|
| 142 |
+
7. Activar en cada proyecto el entorno virtual:
|
| 143 |
+
- Windows: `nombre_del_entorno\Scripts\activate`
|
| 144 |
+
- macOS/Linux: `source nombre_del_entorno/bin/activate`
|
| 145 |
+
8. Instalar las dependencias: `pip install -r requirements.txt`
|
| 146 |
+
|
| 147 |
+
## Estructura del Proyecto
|
| 148 |
+
|
| 149 |
+
1. **Para la parte del Análisis**<br>
|
| 150 |
+
|
| 151 |
+
- `notebooks/`
|
| 152 |
+
- Incluye los siguiente:
|
| 153 |
+
- `assets/`
|
| 154 |
+
- Imagenes ilustrativas.
|
| 155 |
+
- `tablas/`
|
| 156 |
+
- Aca se guardaran los archivos con estructura similar al EDR de la descripción del proyecto.
|
| 157 |
+
- `tablas_dash/`
|
| 158 |
+
- Aca se guardaran tablas especialmenete creadas para darle velocidad a la herramienta de visualización cuando interactúe con el usuario.
|
| 159 |
+
- `db/`
|
| 160 |
+
- Contiene los siguientes archivos:
|
| 161 |
+
- `db/connection.py` Se encarga de la conección con la Base de datos Mysql
|
| 162 |
+
- `db/tables.py` Tiene TODA la estructura del EDR desarrollada en el ORM SqlAlchemy de Python. Funcional para cualquier motor de base de datos SQL, contiene Todas las tablas y sus relaciones.
|
| 163 |
+
- `db/create_tables.py` Script de Python que al ejecutarlo crea la base de tablas y relaciones de la Base de datos
|
| 164 |
+
- `docker/`
|
| 165 |
+
- contiene los siguientes archivos
|
| 166 |
+
- `docker/Dockerfile` Dockerfile de la imagen Mysql
|
| 167 |
+
- `docker/pasos_en_la_terminal.txt` Explicación de lo concerniente a Docker y Mysql
|
| 168 |
+
- `utils/`
|
| 169 |
+
-Contiene archivos con extensión `.py` que tienen funciones que dan soporte a los cuadernos Jupyter notebooks.
|
| 170 |
+
- `01_normalizando_internet.ipynb`
|
| 171 |
+
- Normalización de los datos contenidos en el archivo Internet.xlsx
|
| 172 |
+
- `02_normalizando_otros.ipynb`
|
| 173 |
+
- Normalización de los datos contenidos en los archivos
|
| 174 |
+
- Telefonia_fija.xlsx
|
| 175 |
+
- Telefonia_movil.xlsx
|
| 176 |
+
- Television.xlsx
|
| 177 |
+
- `03_creando_data_tablero.ipynb`
|
| 178 |
+
- Donde se crean unas tablas customizadas para la herramineta de Visualización
|
| 179 |
+
- `04_eda_comparando_tecnologias.ipynb`
|
| 180 |
+
- Análisis de la evolución de los distintos sectores de las telecomunicaciones
|
| 181 |
+
- `05_eda_internet.ipynb`
|
| 182 |
+
- Análisis enfocado en el sector Internet de las telecomunicaciones
|
| 183 |
+
|
| 184 |
+
2. **Para la parte de la App Dash - Herramineta de Visualización**
|
| 185 |
+
|
| 186 |
+
- `data/`: Contiene los archivos `parquet` necesarios para la visualización.
|
| 187 |
+
- `components/`: Carpeta donde se guardan los archivos `.py ` que contienen los distintos componentes de la visualización.
|
| 188 |
+
- `utils/` Guarda un archivo `.py` donde se realizan unos filtros necesarios en la visualización del Mapa de Oportunidades.
|
| 189 |
+
- `main.py` Arhivo raiz de la App de Dash
|
| 190 |
+
- `requirements.txt` dependencias necesarias para la App
|
| 191 |
+
- `README.md`: Archivo de documentación del proyecto.
|
| 192 |
+
|
| 193 |
+
## Uso y Ejecución
|
| 194 |
+
|
| 195 |
+
1. **Para la parte del Análisis**:
|
| 196 |
+
|
| 197 |
+
- Ejecute los siguientes archivos en el Orden que se nombran a continuación:
|
| 198 |
+
- `01_normalizando_internet.ipynb`
|
| 199 |
+
- `02_normalizando_otros.ipynb`
|
| 200 |
+
- `03_creando_data_tablero.ipynb`
|
| 201 |
+
- `04_eda_comparando_tecnologias.ipynb`
|
| 202 |
+
- `05_eda_internet.ipynb`
|
| 203 |
+
|
| 204 |
+
2. **Para la parte de la App de Dash, la Visualización**:
|
| 205 |
+
|
| 206 |
+
- Asegurese de que la estructura de este repositorio, a excepción de la Carpeta `notebooks`, se copió Integramente en la locación de su computador que dispuso para ello.
|
| 207 |
+
- Con el entorno virtual activado ejecute `python main:app` espere que se ejecute y desde el navegador `http://127.0.0.1:8050` para que vaya directamente en la visualización desde su navegador.
|
| 208 |
+
|
| 209 |
+
## Datos y Fuentes
|
| 210 |
+
|
| 211 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 212 |
+
Los Datasets Iniciales fueron extraídos de la del Ente Nacional de Comunicaciones (ENACOM) de Argentina, en su gran Mayoria, sólo el archivo <b>tipos-de-cambio-historicos.csv</b> no viene de allí, este se saco de la pagina del Banco Central de Argentina.
|
| 213 |
+
</p>
|
| 214 |
+
<br>
|
| 215 |
+
|
| 216 |
+
## Metodología
|
| 217 |
+
|
| 218 |
+
1. **Recolección de Datos**
|
| 219 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 220 |
+
Los datos utilizados en este proyecto fueron extraídos del Ente Nacional de Comunicaciones (ENACOM) de Argentina. Se recopilaron datos históricos de los últimos diez años sobre los ingresos y la penetración de mercado en los sectores de Telefonía Fija, Telefonía Móvil, Internet y Televisión.
|
| 221 |
+
</p>
|
| 222 |
+
|
| 223 |
+
2. **Normalización de Datos**
|
| 224 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 225 |
+
Antes de proceder con el análisis, se normalizaron los datos para asegurar su consistencia y precisión. Este proceso incluyó la limpieza de datos, la eliminación de duplicados y la corrección de valores Nulos.
|
| 226 |
+
</p>
|
| 227 |
+
|
| 228 |
+
3. **Creación del Modelo de Datos (EDR)**
|
| 229 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 230 |
+
Se diseñó y creó un modelo de datos en SQL (EDR) que sirve como data warehouse para la empresa. Este modelo organiza los datos de manera eficiente y está preparado para soportar futuros estudios y análisis.
|
| 231 |
+
</p>
|
| 232 |
+
|
| 233 |
+
4. **Análisis de Datos**
|
| 234 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 235 |
+
El análisis se centró en la evolución de los ingresos y la penetración de mercado en los sectores mencionados. Se realizó un estudio detallado del sector de Internet, examinando el comportamiento del mercado en relación con las tecnologías que brindan el servicio, tales como ADSL, WIRELESS, Fibra Óptica y Cable Modem y las distintas Velocidades Medias de Bajada que presentan las conexiones.
|
| 236 |
+
</p>
|
| 237 |
+
|
| 238 |
+
5. **Definición de KPI’s y Métricas**
|
| 239 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 240 |
+
Para una mejor comprensión del comportamiento del sector, se definieron dos KPI’s a nivel de provincias y tres métricas nacionales, todas ellas de seguimiento trimestral, y se encuentran a detalle en la parte de <b>Descripción</b> de este Documento
|
| 241 |
+
</p>
|
| 242 |
+
|
| 243 |
+
6. **Visualización de Datos**
|
| 244 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 245 |
+
Se desarrolló una herramienta interactiva de visualización utilizando Python y el framework Dash de la librería Plotly. Esta herramienta permite a los usuarios explorar los datos de manera intuitiva y obtener insights valiosos.
|
| 246 |
+
</p>
|
| 247 |
+
|
| 248 |
+
7. **Documentación y Presentación**
|
| 249 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 250 |
+
Finalmente, se documentaron todos los procesos y resultados del análisis. La documentación incluye la descripción del modelo de datos, los métodos de análisis utilizados, y las visualizaciones generadas. Esta documentación está diseñada para ser clara y accesible, facilitando su uso por parte de otros analistas y compañeros dentro de la Empresa.
|
| 251 |
+
</p>
|
| 252 |
+
|
| 253 |
+
## Conclusiones
|
| 254 |
+
|
| 255 |
+
1. **Impacto de la Inflación y Devaluación**:
|
| 256 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 257 |
+
La comparación de la evolución del mercado en dólares y pesos Argentinos muestra resultados significativamente diferentes, lo que sugiere la presencia de inflación y/o devaluación durante el período estudiado. Es crucial consultar con economistas y expertos locales antes de realizar inversiones para comprender mejor la situación económica actual.
|
| 258 |
+
</p>
|
| 259 |
+
|
| 260 |
+
2. **Reducción de Ingresos en el Sector de Telecomunicaciones**:
|
| 261 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 262 |
+
En la última década, los ingresos en dólares de los distintos sectores de telecomunicaciones se han reducido a la mitad. El sector de Internet es el único que ha experimentado una caída leve en ingresos, mientras que su penetración en el mercado ha seguido aumentando. Sin embargo, no se dispone de datos sobre los costos de masificación de estas tecnologías, lo que limita el análisis completo del sector.
|
| 263 |
+
</p>
|
| 264 |
+
|
| 265 |
+
3. **Preferencias del Mercado**:
|
| 266 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 267 |
+
Los datos indican una clara preferencia de los consumidores argentinos por servicios de Internet que ofrecen mayores velocidades. Esto se refleja en la disminución drástica de la participación de mercado de la tecnología ADSL y el aumento en la velocidad media de bajada de Internet en los últimos tres años. Las tecnologías dominantes en el mercado actual son CableModem y Fibra Óptica, aunque ambas requieren infraestructura de cableado, lo que puede no ser rentable en áreas de baja densidad poblacional.
|
| 268 |
+
</p>
|
| 269 |
+
|
| 270 |
+
## Recomendaciones
|
| 271 |
+
|
| 272 |
+
1. **Consulta con Expertos Económicos**:
|
| 273 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 274 |
+
Antes de realizar inversiones en el sector de telecomunicaciones en Argentina, es recomendable consultar con economistas y expertos locales para obtener una comprensión detallada de la situación económica y los posibles riesgos asociados.
|
| 275 |
+
</p>
|
| 276 |
+
|
| 277 |
+
2. **Análisis de Costo-Beneficio**:
|
| 278 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 279 |
+
Realizar un análisis de costo-beneficio detallado del sector de Internet es esencial antes de incursionar en él. Esto ayudará a identificar las oportunidades y desafíos específicos del mercado y a tomar decisiones informadas.
|
| 280 |
+
</p>
|
| 281 |
+
|
| 282 |
+
3. **Exploración de Tecnologías Inalámbricas**:
|
| 283 |
+
<p style="text-align: justify; text-indent: 2em;">
|
| 284 |
+
Dado que las tecnologías CableModem y Fibra Óptica tienen limitaciones en áreas de baja densidad poblacional, se recomienda estudiar la viabilidad de tecnologías inalámbricas de alta velocidad, como la tecnología satelital, para penetrar en estos mercados. Esto podría representar una gran oportunidad para expandir la cobertura de Internet en localidades con menor número de habitantes.
|
| 285 |
+
</p>
|
| 286 |
+
|
| 287 |
+
## Autores:
|
| 288 |
+
|
| 289 |
+
Este proyecto fue realizado por: Aliskair Rodríguez.<br>
|
| 290 |
+
[linkedin.com/in/aliskair-rodriguez-782b3641](https://www.linkedin.com/in/aliskair-rodriguez-782b3641/)
|
assets/styles.css
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
body {
|
| 2 |
+
background-color: rgb(30, 30, 30);
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
.work_container {
|
| 6 |
+
width: 98vw;
|
| 7 |
+
height: 93vh;
|
| 8 |
+
display: flex;
|
| 9 |
+
justify-content: space-around;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
.tab_subcontainers{
|
| 13 |
+
margin-top: 1em;
|
| 14 |
+
height: 97%;
|
| 15 |
+
background-color: #2b2b2b;
|
| 16 |
+
border: 0.05em solid #656565;
|
| 17 |
+
border-radius: 0.5em;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
/* TAB HOME */
|
| 21 |
+
#tab_home{
|
| 22 |
+
display: flex;
|
| 23 |
+
flex-direction: column;
|
| 24 |
+
justify-content: space-around;
|
| 25 |
+
width: 99%;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
#title_home{
|
| 29 |
+
margin-top: 3%;
|
| 30 |
+
text-align: center;
|
| 31 |
+
color: #ffffff;
|
| 32 |
+
font-weight: bold;
|
| 33 |
+
font-size: 3.5rem;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
.pestanas{
|
| 37 |
+
font-weight: bold;
|
| 38 |
+
font-size: 1.75rem;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
.textos_pestanas{
|
| 42 |
+
font-weight: normal;
|
| 43 |
+
font-size: 1.5rem;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
.home-content {
|
| 47 |
+
background-color: #2b2b2b;
|
| 48 |
+
padding: 2%;
|
| 49 |
+
color: #ffffff;
|
| 50 |
+
border: 1px solid #ccc;
|
| 51 |
+
border-radius: 5px;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
/* TAB 2 */
|
| 59 |
+
#tab2_left{
|
| 60 |
+
width: 20%;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
#tab2_right{
|
| 64 |
+
width: 78%;
|
| 65 |
+
text-align: center;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
#title_right_tab2{
|
| 69 |
+
margin-top: 0.5rem;
|
| 70 |
+
display: inline-block;
|
| 71 |
+
width: 100%;
|
| 72 |
+
height: 10%;
|
| 73 |
+
color: #ffffff;
|
| 74 |
+
font-weight: bold;
|
| 75 |
+
font-size: 1.5rem;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
#grafico_right_tab2{
|
| 79 |
+
width: 100%;
|
| 80 |
+
height: 89%;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
#container_graficos_tab2{
|
| 84 |
+
width: 100%;
|
| 85 |
+
height: 100%;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
#container_control_slides{
|
| 89 |
+
width: 100%;
|
| 90 |
+
display: flex;
|
| 91 |
+
justify-content: space-around;
|
| 92 |
+
color: #ffffff;
|
| 93 |
+
font-weight: bold;
|
| 94 |
+
font-size: 1.5rem;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
.parrafo_left{
|
| 98 |
+
margin-left: 2%;
|
| 99 |
+
margin-right: 2%;
|
| 100 |
+
color: #ffffff;
|
| 101 |
+
/* font-weight: bold; */
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
/* TAB 3 */
|
| 106 |
+
#tab3_right{
|
| 107 |
+
/* margin-top: 1em; */
|
| 108 |
+
display: flex;
|
| 109 |
+
flex-direction: column;
|
| 110 |
+
justify-content: space-between;
|
| 111 |
+
width: 99%;
|
| 112 |
+
height: 97%;
|
| 113 |
+
text-align: center;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
#zona_tarjeta_tab3{
|
| 117 |
+
height: 18%;
|
| 118 |
+
display: flex;
|
| 119 |
+
justify-content: space-between;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
#drop_tab3{
|
| 123 |
+
width: 24%;
|
| 124 |
+
height: 100%;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
#tarjeta_1{
|
| 129 |
+
width: 24%;
|
| 130 |
+
height: 100%;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
#tarjeta_2{
|
| 134 |
+
width: 24%;
|
| 135 |
+
height: 100%;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
#tarjeta_3{
|
| 139 |
+
width: 24%;
|
| 140 |
+
height: 100%;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
#zona_grafica_tab3{
|
| 144 |
+
height: 80%;
|
| 145 |
+
display: flex;
|
| 146 |
+
justify-content:space-between;
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
#zona_barras_tab3{
|
| 150 |
+
width: 60%;
|
| 151 |
+
height: 100%;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
#barras_tab3{
|
| 155 |
+
width: 100%;
|
| 156 |
+
height: 100%;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
#zona_pies_tab3{
|
| 160 |
+
width: 39%;
|
| 161 |
+
height: 100%;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
#pies_tab3{
|
| 165 |
+
width: 100%;
|
| 166 |
+
height: 100%;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
#grafico_rangos_tab3{
|
| 170 |
+
width: 60%;
|
| 171 |
+
height: 60%;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
#label_periodo{
|
| 175 |
+
margin-top: 4%;
|
| 176 |
+
text-align: left;
|
| 177 |
+
font-size: 1.3rem;
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
#grafico_barras_tab3{
|
| 181 |
+
display: flex;
|
| 182 |
+
flex-direction: column;
|
| 183 |
+
justify-content: space-between;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
.tarjetas{
|
| 187 |
+
color: #ffffff;
|
| 188 |
+
font-weight: bold;
|
| 189 |
+
font-size: 2.5rem;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
#pie_pagina_tab3{
|
| 193 |
+
font-size: 1.2rem;
|
| 194 |
+
color: #ffffff;
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
/* TAB 4 */
|
| 199 |
+
#tab4_left{
|
| 200 |
+
width: 20%;
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
#tab4_center{
|
| 204 |
+
width: 37%;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
#tab4_right{
|
| 208 |
+
width: 40%;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
.one_drop_tab4{
|
| 212 |
+
width: 90%;
|
| 213 |
+
color: #ffffff;
|
| 214 |
+
font-weight: bold;
|
| 215 |
+
margin-left: 5%;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
#tab4_rangos_response{
|
| 219 |
+
width: 100%;
|
| 220 |
+
text-align: center;
|
| 221 |
+
color: #ffffff;
|
| 222 |
+
font-weight: bold
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
#texto_tab4{
|
| 226 |
+
display: inline-block;
|
| 227 |
+
color: #ffffff;
|
| 228 |
+
font-weight: bold;
|
| 229 |
+
font-size: 1.3rem;
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
#tab4_texto_resultados{
|
| 235 |
+
width: 100%;
|
| 236 |
+
text-align: center;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
#contenedor_pies_tab4{
|
| 240 |
+
margin-top: 2%;
|
| 241 |
+
text-align: center;
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
/* LETRAS DROPS */
|
| 246 |
+
|
| 247 |
+
.title_left{
|
| 248 |
+
margin-top: 3%;
|
| 249 |
+
text-align: center;
|
| 250 |
+
color: #ffffff;
|
| 251 |
+
font-weight: bold;
|
| 252 |
+
font-size: 1.5rem;
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
.titles{
|
| 256 |
+
margin-top: 3%;
|
| 257 |
+
text-align: center;
|
| 258 |
+
/* color: #d2d0ce; */
|
| 259 |
+
color: #ffffff;
|
| 260 |
+
font-weight: bold;
|
| 261 |
+
font-size: 1.5rem;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.tab_left{
|
| 265 |
+
height: 100%;
|
| 266 |
+
width: 100%;
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
.btns{
|
| 270 |
+
display: inline-block;
|
| 271 |
+
/* background-color: #70cbff; */
|
| 272 |
+
background-color: #ffffff;
|
| 273 |
+
width: 30%;
|
| 274 |
+
height: 2rem;
|
| 275 |
+
border-radius: 0.3rem;
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
.btn-container{
|
| 279 |
+
width: 100%;
|
| 280 |
+
text-align: center;
|
| 281 |
+
}
|
components/component_home.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
|
| 3 |
+
component_home = html.Div([
|
| 4 |
+
html.Div([
|
| 5 |
+
html.Div([
|
| 6 |
+
html.Div(html.Label("Telecomunicaciones Argentina"), id='title_home'),
|
| 7 |
+
html.Br(),
|
| 8 |
+
html.Br(),
|
| 9 |
+
html.Br(),
|
| 10 |
+
html.Ul([
|
| 11 |
+
html.Li([
|
| 12 |
+
"¿Porqué Internet?:",
|
| 13 |
+
html.Ul([
|
| 14 |
+
html.Li("Análisis del comportamiento de las Distintas Tecnologías de Telecomunicación")
|
| 15 |
+
], className='textos_pestanas')
|
| 16 |
+
], id="contexto", className="pestanas"),
|
| 17 |
+
html.Br(),
|
| 18 |
+
html.Br(),
|
| 19 |
+
html.Li([
|
| 20 |
+
"Seguimiento a Métricas:",
|
| 21 |
+
html.Ul([
|
| 22 |
+
html.Li("Seguimiento a los Indicadores de Gestión Trimestrales del Internet")
|
| 23 |
+
], className='textos_pestanas')
|
| 24 |
+
], id="tablero", className="pestanas"),
|
| 25 |
+
html.Br(),
|
| 26 |
+
html.Br(),
|
| 27 |
+
html.Li([
|
| 28 |
+
"Mapa de Oportunidades:",
|
| 29 |
+
html.Ul([
|
| 30 |
+
html.Li("Mapa de seguimiento de Oportunidades por Rangos de Población")
|
| 31 |
+
], className='textos_pestanas')
|
| 32 |
+
], id="mapa", className="pestanas")
|
| 33 |
+
])
|
| 34 |
+
|
| 35 |
+
], className="home-content"),
|
| 36 |
+
], id='tab_home'),
|
| 37 |
+
], className='work_container', id='tab2_component')
|
components/component_tab2.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
from components.component_tab2_left import component_tab2_left
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
component_tab_2 = html.Div([
|
| 6 |
+
html.Div([component_tab2_left], className='tab_subcontainers', id='tab2_left'),
|
| 7 |
+
html.Div([
|
| 8 |
+
html.Div([], id='title_right_tab2'),
|
| 9 |
+
html.Div([], id='grafico_right_tab2'),
|
| 10 |
+
], className='tab_subcontainers', id='tab2_right')
|
| 11 |
+
], className='work_container', id='tab2_component')
|
components/component_tab2_grafico.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import polars as pl
|
| 2 |
+
from dash import html, dcc
|
| 3 |
+
import plotly.express as px
|
| 4 |
+
import plotly.graph_objects as go
|
| 5 |
+
from plotly.subplots import make_subplots
|
| 6 |
+
|
| 7 |
+
internet_pais = pl.read_parquet('data/internet_tab2.parquet')
|
| 8 |
+
telefonia_movil = pl.read_parquet('data/telefonia_movil_tab2.parquet')
|
| 9 |
+
telefonia_fija = pl.read_parquet('data/telefonia_fija_tab2.parquet')
|
| 10 |
+
television = pl.read_parquet('data/television_tab2.parquet')
|
| 11 |
+
df_pies = pl.read_parquet('data/df_pie_tab2.parquet')
|
| 12 |
+
tecnologias_grafico_9 = pl.read_parquet('data/tecnologias_internet_graficos_tab2.parquet')
|
| 13 |
+
rangos_grafico_10 = pl.read_parquet('data/rangos_internet_graficos_tab2.parquet')
|
| 14 |
+
|
| 15 |
+
# Listas de Dataframes, Nombres de Graficos y Colores Para los Gráficos con 4 Lineas
|
| 16 |
+
dfs_4 = [internet_pais, telefonia_movil, telefonia_fija, television]
|
| 17 |
+
list_4 = ["Internet", "Telefonía Móvil", "Telefonía Fija", "Televisión"]
|
| 18 |
+
colors_4 = ['#22D3EE', '#38C172', '#F6993F', '#FFED4A']
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
# Listas de Datagrames, Nombres de Graficos y Colores Para los Gráficos con 3 Lineas
|
| 22 |
+
dfs_3 = [internet_pais, telefonia_fija, television]
|
| 23 |
+
list_3 = ["Internet", "Telefonía Fija", "Televisión"]
|
| 24 |
+
colors_3 = ['#22D3EE', '#F6993F', '#FFED4A']
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# ESTA FUNCION CREA LAS GRAFICAS 1, 2 y 4 del Tab 2
|
| 28 |
+
def crear_grafica(df_list: list, y_column: str, list_names: list, colors: list) -> px.line:
|
| 29 |
+
"""Crear gráfica: Función para crear gráficas de tendencias
|
| 30 |
+
|
| 31 |
+
Args:
|
| 32 |
+
df_list (list): Lista de Dataframes
|
| 33 |
+
y_column (str): Columna del dataframe a graficar
|
| 34 |
+
title (str): Título del gráfico
|
| 35 |
+
list_names (list): Lista de Nombres de los gráficos
|
| 36 |
+
colors (list): Lista de Colores
|
| 37 |
+
|
| 38 |
+
Returns:
|
| 39 |
+
px.line: Grafica de linea de la Libreria plotly
|
| 40 |
+
"""
|
| 41 |
+
fig = px.line()
|
| 42 |
+
# Aca esto es como 3 ciclos for en paralelo cada variable
|
| 43 |
+
for df, name, color in zip(df_list, list_names, colors):
|
| 44 |
+
fig.add_scatter(x=df["fecha"], y=df[y_column], mode='lines', name=name, line=dict(color=color))
|
| 45 |
+
|
| 46 |
+
fig.update_layout(
|
| 47 |
+
xaxis_title='Periodo',
|
| 48 |
+
yaxis_title=y_column,
|
| 49 |
+
font=dict(color='#ffffff', size=16),
|
| 50 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 51 |
+
plot_bgcolor='rgba(0,0,0,0)', # Fondo de la grilla transparente
|
| 52 |
+
xaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 53 |
+
yaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 54 |
+
height=600,
|
| 55 |
+
)
|
| 56 |
+
return fig
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
# ESTA SOLO HACE EL GRAFICO DE TORTAS DEL TAB 2
|
| 60 |
+
def crear_graf_pie(df: pl.DataFrame, colors: list):
|
| 61 |
+
"""crear_graf_pie: Crea un Subplot de Pies de Plotly. Muestran la comparación
|
| 62 |
+
de ingresos en Dolares entre 2014 y 2024 en la Tab 2 "¿Porqué Internet?
|
| 63 |
+
|
| 64 |
+
Args:
|
| 65 |
+
df (pl.DataFrame): Dataframe con la información
|
| 66 |
+
colors (list): ancho del gráfico
|
| 67 |
+
|
| 68 |
+
Returns:
|
| 69 |
+
go.Fig: Suplots de Pies de la Libreria Plotly
|
| 70 |
+
"""
|
| 71 |
+
|
| 72 |
+
fig = make_subplots(rows=1, cols=2, specs=[[{'type': 'pie'}, {'type': 'pie'}]],
|
| 73 |
+
subplot_titles=("Ingresos 2014", "Ingresos 2024"))
|
| 74 |
+
|
| 75 |
+
# Gráfico de Pie para Ingresos 2014
|
| 76 |
+
fig.add_trace(go.Pie(labels=df["Tecnología"], values=df["Ingresos 2014"],
|
| 77 |
+
name="Ingresos 2014", marker=dict(colors=colors), scalegroup='one'), row=1, col=1)
|
| 78 |
+
|
| 79 |
+
# Gráfico de Pie para Ingresos 2024 con tamaño proporcional
|
| 80 |
+
fig.add_trace(go.Pie(labels=df["Tecnología"], values=df["Ingresos 2024"],
|
| 81 |
+
name="Ingresos 2024", marker=dict(colors=colors), scalegroup='one'), row=1, col=2)
|
| 82 |
+
|
| 83 |
+
fig.update_layout(
|
| 84 |
+
font=dict(color='#ffffff', size=16),
|
| 85 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 86 |
+
height=600,
|
| 87 |
+
annotations=[dict(text='2014', x=0.22, y=1.0, font_size=24, showarrow=False),
|
| 88 |
+
dict(text='2024', x=0.77, y=0.85, font_size=24, showarrow=False),
|
| 89 |
+
])
|
| 90 |
+
|
| 91 |
+
return fig
|
| 92 |
+
|
| 93 |
+
# ESTA FUNCION CREA LAS GRAFICAS 6 y 7 del Tab 2
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def crear_graf_df(columns: list, names: list, colors: list, y_title: str, df: pl.DataFrame) -> px.line:
|
| 97 |
+
"""crear_graf_df: recibe de un mismo Dataframe la inf necesaria para graficar la tendencia de varias
|
| 98 |
+
columnas
|
| 99 |
+
|
| 100 |
+
Args:
|
| 101 |
+
columns (list): Lista con los nombres de las columnas a Graficar
|
| 102 |
+
names (list): Lista con los nombres de Cada Linea en el Gráfico
|
| 103 |
+
colors (list): Lista con los colores usar en el Gráfico
|
| 104 |
+
y_title (str): Titulo del eje y
|
| 105 |
+
df (pl.DataFrame): Dataframe del cual se sacarán los datos a graficar
|
| 106 |
+
|
| 107 |
+
Returns:
|
| 108 |
+
px.line: Grafico tipo linea de la libreria plotly
|
| 109 |
+
"""
|
| 110 |
+
|
| 111 |
+
fig = px.line()
|
| 112 |
+
for i in range(3):
|
| 113 |
+
fig.add_scatter(x=df['fecha'], y=df[columns[i]],
|
| 114 |
+
name=names[i], mode='lines', line=dict(color=colors[i]))
|
| 115 |
+
fig.update_layout(
|
| 116 |
+
xaxis_title='Periodo',
|
| 117 |
+
yaxis_title=y_title,
|
| 118 |
+
font=dict(color='#ffffff', size=16),
|
| 119 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 120 |
+
plot_bgcolor='rgba(0,0,0,0)', # Fondo de la grilla transparente
|
| 121 |
+
xaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 122 |
+
yaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 123 |
+
height=580,
|
| 124 |
+
margin=dict(l=100, r=0, t=0, b=0)
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
return fig
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
# ESTA FUNCION CREA LA TABLA DE LA DIAPOSITIVA 8 DEL CONTEXTO
|
| 131 |
+
def crear_tabla(df: pl.DataFrame) -> go.Figure:
|
| 132 |
+
"""crear_tabla: Crea la tabla donde se comparan las Variaciones de Ingresos
|
| 133 |
+
y accesos de las distintas tecnologías en el 04_eda_comparando_tecnologias.ipynb
|
| 134 |
+
|
| 135 |
+
Args:
|
| 136 |
+
df (pl.DataFrame): Dataframe con la información a mostrar en la tabla
|
| 137 |
+
|
| 138 |
+
Returns:
|
| 139 |
+
go.Fig: Tabla de la Libreria Plotly
|
| 140 |
+
"""
|
| 141 |
+
df = df.with_columns([
|
| 142 |
+
((pl.col('Accesos 2024') / pl.col('Accesos 2014')) - 1).alias('Variación Accesos'),
|
| 143 |
+
((pl.col('Ingresos 2024') / pl.col('Ingresos 2014')) - 1).alias('Variación Ingresos')
|
| 144 |
+
])
|
| 145 |
+
lista_varia_accesos = []
|
| 146 |
+
lista_varia_ingresos = []
|
| 147 |
+
for i in range(4):
|
| 148 |
+
lista_varia_accesos.append(str(round((df[i, 5] * 100), 2)) + ' %')
|
| 149 |
+
lista_varia_ingresos.append(str(round((df[i, 6] * 100), 2)) + ' %')
|
| 150 |
+
|
| 151 |
+
header = dict(values=['Tecnología', 'Variación Accesos', 'Variación Ingresos'],
|
| 152 |
+
fill_color='lavender',
|
| 153 |
+
align='center')
|
| 154 |
+
|
| 155 |
+
cells = dict(values=[
|
| 156 |
+
['Internet', 'Telefonía Móvil', 'Telefonía Fija', 'Televisión'],
|
| 157 |
+
lista_varia_accesos,
|
| 158 |
+
lista_varia_ingresos
|
| 159 |
+
],
|
| 160 |
+
fill_color=[['#22D3EE', '#38C172', '#F6993F', '#FFED4A'], # Colores personalizados para cada fila
|
| 161 |
+
['#22D3EE', '#38C172', '#F6993F', '#FFED4A'], # Colores de fondo para Variación Accesos
|
| 162 |
+
['#22D3EE', '#38C172', '#F6993F', '#FFED4A']], # Colores de fondo para Variación Ingresos
|
| 163 |
+
align=['left', 'center', 'center'],
|
| 164 |
+
height=30,
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
fig = go.Figure(data=[go.Table(header=header, cells=cells, columnwidth=[300, 300, 300],)])
|
| 168 |
+
|
| 169 |
+
# Ajustar el layout para que se ajuste al tamaño de la tabla
|
| 170 |
+
fig.update_layout(
|
| 171 |
+
font=dict(color='black', size=18),
|
| 172 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 173 |
+
width=800,
|
| 174 |
+
height=600,
|
| 175 |
+
margin=dict(l=300, r=0, t=170, b=0)
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
# Retorna la tabla
|
| 179 |
+
return fig
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
# FUNCION QUE DEVUELVE LAS GRAFICAS DE LAS DIAPOSITIVAS 9 Y 10
|
| 183 |
+
def crea_graficas_9_10(df: pl.DataFrame, num_diapositiva: int) -> px.line:
|
| 184 |
+
"""Se encarga de Graficar las Diapositivas 9 y 10 de la Tab2 "¿Porqué Internet?
|
| 185 |
+
|
| 186 |
+
Args:
|
| 187 |
+
df (pl.DataFrame): Dataframe con los Datos a Graficar
|
| 188 |
+
num_diapositiva (int): Numero de la Diapositiva a representar
|
| 189 |
+
|
| 190 |
+
Returns:
|
| 191 |
+
px.Line: Grafico de Lineas de Tendencias de Rangos de Velocidad o Tecnologias (según
|
| 192 |
+
sea el parámetro num_diapositiva recibido) de la libreria Plotly Express
|
| 193 |
+
"""
|
| 194 |
+
if num_diapositiva == 9:
|
| 195 |
+
columns = ['ADSL', 'CABLEMODEM', 'FIBRA', 'WIRELESS']
|
| 196 |
+
colors = ['#FFA15A', '#19D3F3', '#FF6692', '#B6E880']
|
| 197 |
+
else:
|
| 198 |
+
colors = ['#636EFA', '#EF553B', '#00CC96', '#AB63FA']
|
| 199 |
+
columns = ['Hasta 10 Mbps', '10.01 - 30 Mbps', '30.01 - 100 Mbps', 'Mayor a 100 Mbps']
|
| 200 |
+
names = columns
|
| 201 |
+
|
| 202 |
+
fig = px.line()
|
| 203 |
+
for i in range(len(columns)):
|
| 204 |
+
fig.add_scatter(x=df['Fecha'], y=df[columns[i]],
|
| 205 |
+
name=names[i], mode='lines', line=dict(color=colors[i]))
|
| 206 |
+
fig.update_layout(
|
| 207 |
+
xaxis_title='Periodo',
|
| 208 |
+
yaxis_title='Cantidad de Accesos',
|
| 209 |
+
font=dict(color='#ffffff', size=16),
|
| 210 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 211 |
+
plot_bgcolor='rgba(0,0,0,0)', # Fondo de la grilla transparente
|
| 212 |
+
xaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 213 |
+
yaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 214 |
+
# width=800,
|
| 215 |
+
height=580,
|
| 216 |
+
margin=dict(l=100, r=0, t=0, b=0)
|
| 217 |
+
)
|
| 218 |
+
return fig
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def retorna_grafico_tab2(numero_graf: int) -> html.Div:
|
| 222 |
+
"""retorna_grafico_tab2: Según sea el numero de grafico solicitado se apoya en las funciones
|
| 223 |
+
que se encuentran en este mismo archivo para solicitarles la grafica,
|
| 224 |
+
y encapsularla dentro de un dcc.Graph que va a ser contenido en un
|
| 225 |
+
contenedor html.Div.
|
| 226 |
+
Hablamos de los Graficos de la Pestaña o Tab 2 "¿Porqué Internet?
|
| 227 |
+
|
| 228 |
+
Args:
|
| 229 |
+
numero_graf (int): Numero de grafico solicitado
|
| 230 |
+
|
| 231 |
+
Returns:
|
| 232 |
+
html.Div: Componente con el Grafico a Devolver
|
| 233 |
+
"""
|
| 234 |
+
if numero_graf in [1, 2, 4]:
|
| 235 |
+
if numero_graf == 1:
|
| 236 |
+
fig = crear_grafica(df_list=dfs_4, y_column='ingresos_miles',
|
| 237 |
+
list_names=list_4, colors=colors_4)
|
| 238 |
+
elif numero_graf == 2:
|
| 239 |
+
fig = crear_grafica(df_list=dfs_4, y_column='ingresos_dolar_miles',
|
| 240 |
+
list_names=list_4, colors=colors_4)
|
| 241 |
+
else:
|
| 242 |
+
fig = crear_grafica(df_list=dfs_3, y_column='accesos_100_hab',
|
| 243 |
+
list_names=list_3, colors=colors_3)
|
| 244 |
+
elif numero_graf == 3:
|
| 245 |
+
fig = fig = crear_graf_pie(df=df_pies, colors=colors_4)
|
| 246 |
+
elif numero_graf in [5, 6, 7]:
|
| 247 |
+
if numero_graf == 5:
|
| 248 |
+
columns = ['total_accesos_post', 'total_accesos_pre', 'total_accesos']
|
| 249 |
+
names = ['Accesos Post-Pagos', 'Accesos Pre-Pagos', 'Total Accesos']
|
| 250 |
+
y_title = 'Accesos'
|
| 251 |
+
elif numero_graf == 6:
|
| 252 |
+
columns = ['llamadas_post_miles', 'llamadas_pre_miles', 'total_llamadas']
|
| 253 |
+
names = ['Llamadas Post-Pagos (miles)', 'Llamadas Pre-Pagos (miles)', 'Total Llamadas (miles)']
|
| 254 |
+
y_title = 'Llamadas'
|
| 255 |
+
else:
|
| 256 |
+
columns = ['minutos_post_miles', 'minutos_pre_miles', 'total_minutos']
|
| 257 |
+
names = ['Minutos Post-Pagos (miles)', 'Minutos Pre-Pagos (miles)', 'Total Minutos (miles)']
|
| 258 |
+
y_title = 'Minutos'
|
| 259 |
+
colors = ['#9fbc12', ' #045426 ', '#38C172']
|
| 260 |
+
fig = crear_graf_df(columns=columns, names=names, colors=colors,
|
| 261 |
+
y_title=y_title, df=telefonia_movil)
|
| 262 |
+
elif numero_graf == 8:
|
| 263 |
+
fig = crear_tabla(df=df_pies)
|
| 264 |
+
elif numero_graf == 9:
|
| 265 |
+
fig = crea_graficas_9_10(df=tecnologias_grafico_9.sort('Fecha'), num_diapositiva=9)
|
| 266 |
+
elif numero_graf == 10:
|
| 267 |
+
fig = crea_graficas_9_10(df=rangos_grafico_10.sort('Fecha'), num_diapositiva=10)
|
| 268 |
+
|
| 269 |
+
config = {'displayModeBar': False}
|
| 270 |
+
|
| 271 |
+
componente_graf_tab4 = html.Div([
|
| 272 |
+
dcc.Graph(figure=fig, config=config)
|
| 273 |
+
])
|
| 274 |
+
return componente_graf_tab4
|
components/component_tab2_left.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
import dash_daq as daq
|
| 3 |
+
|
| 4 |
+
component_tab2_left = html.Div([
|
| 5 |
+
html.Div(html.Label("Tendencias Tecnologías"), className='title_left'),
|
| 6 |
+
html.Br(),
|
| 7 |
+
html.Br(),
|
| 8 |
+
html.Div([
|
| 9 |
+
html.Label("Diapositiva Número "),
|
| 10 |
+
daq.NumericInput(
|
| 11 |
+
id='control_slides_tab2',
|
| 12 |
+
value=0,
|
| 13 |
+
min=0,
|
| 14 |
+
max=10,
|
| 15 |
+
size=60,
|
| 16 |
+
style={'backgroundColor': '#f0f0f0'} # Cambia el color de fondo aquí
|
| 17 |
+
),
|
| 18 |
+
], id='container_control_slides'),
|
| 19 |
+
html.Br(),
|
| 20 |
+
html.Br(),
|
| 21 |
+
html.Br(),
|
| 22 |
+
html.Br(),
|
| 23 |
+
html.Div(id='texto_tab2')
|
| 24 |
+
])
|
components/component_tab2_textos.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
|
| 3 |
+
componente_1 = html.Div([
|
| 4 |
+
html.Div(html.Label('Importante Analizar'), className='title_left'),
|
| 5 |
+
html.Br(),
|
| 6 |
+
html.Div([
|
| 7 |
+
html.P([
|
| 8 |
+
'Desde el Año ',
|
| 9 |
+
html.B('2018'),
|
| 10 |
+
' al ',
|
| 11 |
+
html.B('2024'),
|
| 12 |
+
' se observa un aumento superior a ',
|
| 13 |
+
html.B('1000 %'),
|
| 14 |
+
' !!!'
|
| 15 |
+
], style={
|
| 16 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 17 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 18 |
+
'text-align': 'justify', # Justificado
|
| 19 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 20 |
+
})
|
| 21 |
+
], className='parrafo_left')
|
| 22 |
+
])
|
| 23 |
+
|
| 24 |
+
componente_2 = html.Div([
|
| 25 |
+
html.Div(html.Label('Analizando lo Observado'), className='title_left'),
|
| 26 |
+
html.Br(),
|
| 27 |
+
html.Div([
|
| 28 |
+
html.P([
|
| 29 |
+
'Escenario de Inflación y/o Devaluación Local',
|
| 30 |
+
], style={
|
| 31 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 32 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 33 |
+
'text-align': 'justify', # Justificado
|
| 34 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 35 |
+
})
|
| 36 |
+
], className='parrafo_left')
|
| 37 |
+
])
|
| 38 |
+
|
| 39 |
+
componente_3 = html.Div([
|
| 40 |
+
html.Div(html.Label('Analizando lo Observado'), className='title_left'),
|
| 41 |
+
html.Br(),
|
| 42 |
+
html.Div([
|
| 43 |
+
html.P([
|
| 44 |
+
'Ingresos de 2024 representan ',
|
| 45 |
+
html.B('48.79 %'),
|
| 46 |
+
' con respecto a 2014'
|
| 47 |
+
], style={
|
| 48 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 49 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 50 |
+
'text-align': 'justify', # Justificado
|
| 51 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 52 |
+
})
|
| 53 |
+
], className='parrafo_left')
|
| 54 |
+
])
|
| 55 |
+
|
| 56 |
+
componente_4 = html.Div([
|
| 57 |
+
html.Div(html.Label('Analizando lo Observado'), className='title_left'),
|
| 58 |
+
html.Br(),
|
| 59 |
+
html.Div([
|
| 60 |
+
html.P([
|
| 61 |
+
'Claramente Internet es la única Tecnología que aumento su ',
|
| 62 |
+
'penetración de Mercado'
|
| 63 |
+
], style={
|
| 64 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 65 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 66 |
+
'text-align': 'justify', # Justificado
|
| 67 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 68 |
+
})
|
| 69 |
+
], className='parrafo_left')
|
| 70 |
+
])
|
| 71 |
+
|
| 72 |
+
componente_7 = html.Div([
|
| 73 |
+
html.Div(html.Label('Analizando lo Observado'), className='title_left'),
|
| 74 |
+
html.Br(),
|
| 75 |
+
html.Div([
|
| 76 |
+
html.P([
|
| 77 |
+
'A pesar de la caida de minutos consumidos y llamadas realizadas los ',
|
| 78 |
+
'accesos a la Telefonía Móvil han variado MUY POCO'
|
| 79 |
+
], style={
|
| 80 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 81 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 82 |
+
'text-align': 'justify', # Justificado
|
| 83 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 84 |
+
})
|
| 85 |
+
], className='parrafo_left')
|
| 86 |
+
])
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
componente_8 = html.Div([
|
| 90 |
+
html.Div(html.Label('Queda Muy Claro !!!'), className='title_left'),
|
| 91 |
+
html.Br(),
|
| 92 |
+
html.Div([
|
| 93 |
+
html.P([
|
| 94 |
+
'EL Internet es la Tecnología de Telecomunicaciones con mayor avance ',
|
| 95 |
+
'de penetración en la última Decada'
|
| 96 |
+
], style={
|
| 97 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 98 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 99 |
+
'text-align': 'justify', # Justificado
|
| 100 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 101 |
+
})
|
| 102 |
+
], className='parrafo_left')
|
| 103 |
+
])
|
| 104 |
+
|
| 105 |
+
componente_9 = html.Div([
|
| 106 |
+
html.Div(html.Label('A tener en Cuenta !!!'), className='title_left'),
|
| 107 |
+
html.Br(),
|
| 108 |
+
html.Div([
|
| 109 |
+
html.P([
|
| 110 |
+
'A pesar de que los Accesos a Internet han venido creciendo con el tiempo ',
|
| 111 |
+
'se observan tipos de tecnologías para acceder a ella, que vienen en declive'
|
| 112 |
+
], style={
|
| 113 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 114 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 115 |
+
'text-align': 'justify', # Justificado
|
| 116 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 117 |
+
})
|
| 118 |
+
], className='parrafo_left')
|
| 119 |
+
])
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
componente_10 = html.Div([
|
| 123 |
+
html.Div(html.Label('Acá puede haber una Oportunidad'), className='title_left'),
|
| 124 |
+
html.Br(),
|
| 125 |
+
html.Div([
|
| 126 |
+
html.P([
|
| 127 |
+
'Es claro que la población desea migrar a servicios de Internet, que les ofrezcan ',
|
| 128 |
+
'una conexión de mayor velocidad, por eso la migración hacia FIBRA OPTICA y CABLEMODEM, ',
|
| 129 |
+
'en deprimento de ADSL y WIFI'
|
| 130 |
+
], style={
|
| 131 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 132 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 133 |
+
'text-align': 'justify', # Justificado
|
| 134 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 135 |
+
}),
|
| 136 |
+
html.Br(),
|
| 137 |
+
html.P([
|
| 138 |
+
'PEEERO y en aquellas Localidades donde la Densidad de Población No Justifique un Cableado ??? ',
|
| 139 |
+
], style={
|
| 140 |
+
'text-indent': '1.5rem', # Sangría del párrafo
|
| 141 |
+
'line-height': '1.6', # Espacio de interlineado
|
| 142 |
+
'text-align': 'justify', # Justificado
|
| 143 |
+
'font-size': '1.1rem' # Tamaño de la letra
|
| 144 |
+
}),
|
| 145 |
+
], className='parrafo_left')
|
| 146 |
+
])
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
textos_left_tab2 = [
|
| 150 |
+
componente_1,
|
| 151 |
+
componente_2,
|
| 152 |
+
componente_3,
|
| 153 |
+
componente_4,
|
| 154 |
+
None,
|
| 155 |
+
None,
|
| 156 |
+
componente_7,
|
| 157 |
+
componente_8,
|
| 158 |
+
componente_9,
|
| 159 |
+
componente_10
|
| 160 |
+
]
|
components/component_tab3.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
from components.component_tab3_drop import retorna_tab3_drop
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def retorna_tab3(periodos: list) -> html.Div:
|
| 6 |
+
"""retorna_tab3: Componente que encapsula Todo el Tablero de la Visualización
|
| 7 |
+
|
| 8 |
+
Args:
|
| 9 |
+
periodos (list): Lista de periodos a mostrar en el Drop
|
| 10 |
+
|
| 11 |
+
Returns:
|
| 12 |
+
html.Div: Contenedor General del Tablero
|
| 13 |
+
"""
|
| 14 |
+
component_tab_3 = html.Div([
|
| 15 |
+
# html.Div([retorna_tab3_left(periodos=periodos)], className='tab_subcontainers', id='tab3_left'),
|
| 16 |
+
html.Div([
|
| 17 |
+
html.Div([
|
| 18 |
+
html.Div([retorna_tab3_drop(periodos=periodos)], className='tab_subcontainers', id='drop_tab3'),
|
| 19 |
+
html.Div([], className='tab_subcontainers', id='tarjeta_1'),
|
| 20 |
+
html.Div([], className='tab_subcontainers', id='tarjeta_2'),
|
| 21 |
+
html.Div([], className='tab_subcontainers', id='tarjeta_3'),
|
| 22 |
+
], id='zona_tarjeta_tab3'),
|
| 23 |
+
html.Div([
|
| 24 |
+
html.Div([
|
| 25 |
+
html.Div([], className='tab_subcontainers', id='barras_tab3'),
|
| 26 |
+
], id='zona_barras_tab3'),
|
| 27 |
+
html.Div([
|
| 28 |
+
html.Div([], className='tab_subcontainers', id='pies_tab3'),
|
| 29 |
+
], id='zona_pies_tab3')
|
| 30 |
+
|
| 31 |
+
], id='zona_grafica_tab3')
|
| 32 |
+
], id='tab3_right')
|
| 33 |
+
], className='work_container', id='tab3_component')
|
| 34 |
+
return component_tab_3
|
components/component_tab3_barras.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import plotly.express as px
|
| 2 |
+
from dash import dcc, html
|
| 3 |
+
import polars as pl
|
| 4 |
+
import pandas as pd
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def retorna_barras_tab3(df: pl.DataFrame) -> html.Div:
|
| 8 |
+
"""retorna_barras_tab3: Retorna el Grafico de Barras que se muestra en el Tablero
|
| 9 |
+
|
| 10 |
+
Args:
|
| 11 |
+
df (pl.DataFrame): Dataframe con los datos necesarios para realizar el Gráfico
|
| 12 |
+
|
| 13 |
+
Returns:
|
| 14 |
+
html.Div: Contenedor con el Grafico de Barras
|
| 15 |
+
"""
|
| 16 |
+
df = df.to_pandas()
|
| 17 |
+
|
| 18 |
+
df_grouped = df.melt(id_vars='Provincia',
|
| 19 |
+
value_vars=['Accesos 100 Hog', 'MBPS Media Bajada'],
|
| 20 |
+
var_name='Metrica',
|
| 21 |
+
value_name='Valor')
|
| 22 |
+
|
| 23 |
+
df_grouped = pd.merge(df_grouped, df[['Provincia', 'Accesos 100 Hog Anterior', 'KPI 100 Hog',
|
| 24 |
+
'Cumplimineto KPI 100 Hog', 'Crecimiento Trimestral Accesos 100 Hog',
|
| 25 |
+
'MBPS Anterior', 'KPI MBPS', 'Cumplimineto KPI MBPS',
|
| 26 |
+
'Crecimiento Trimestral MBPS', 'Accesos 100 Hog', 'MBPS Media Bajada']],
|
| 27 |
+
on='Provincia', how='left')
|
| 28 |
+
|
| 29 |
+
fig = px.bar(df_grouped, x='Provincia', y='Valor', color='Metrica', barmode='group',
|
| 30 |
+
custom_data=df_grouped)
|
| 31 |
+
|
| 32 |
+
fig.update_traces(
|
| 33 |
+
hovertemplate="<br>".join([
|
| 34 |
+
"<b>Provincia: %{customdata[0]}</b>",
|
| 35 |
+
"Accesos 100 Hog del Trimestre: %{customdata[11]}",
|
| 36 |
+
"MBPS del Trimestre: %{customdata[12]}",
|
| 37 |
+
"</br>"
|
| 38 |
+
"<b>KPI Accesos 100 Hog: Crecimiento Trimestral 2%</b>",
|
| 39 |
+
"Valor Anterior: %{customdata[3]}",
|
| 40 |
+
"<b>Objetivo KPI: %{customdata[4]}</b>",
|
| 41 |
+
"<b>Cumplimiento KPI: %{customdata[5]} %</b>",
|
| 42 |
+
"Crecimiento Trimestral: %{customdata[6]} %",
|
| 43 |
+
"<br>"
|
| 44 |
+
"<b>KPI MBPS: Crecimiento Trimestral 5%</b>",
|
| 45 |
+
"Valor Anterior: %{customdata[7]}",
|
| 46 |
+
"<b>Objetivo KPI: %{customdata[8]}</b>",
|
| 47 |
+
"<b>Cumplimiento KPI: %{customdata[9]} % </b>",
|
| 48 |
+
"Crecimiento Trimestral: %{customdata[10]} %",
|
| 49 |
+
]),
|
| 50 |
+
hoverlabel=dict(bgcolor="white", font_color="black", font_size=16),
|
| 51 |
+
width=0.4,
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
fig.update_layout(
|
| 55 |
+
xaxis_title="",
|
| 56 |
+
yaxis_title="Accesos",
|
| 57 |
+
font=dict(color='#ffffff', size=14),
|
| 58 |
+
plot_bgcolor='rgba(0,0,0,0)',
|
| 59 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 60 |
+
xaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff', tickangle=-90),
|
| 61 |
+
yaxis=dict(showgrid=False, zeroline=True, linecolor='#ffffff'),
|
| 62 |
+
legend=dict(
|
| 63 |
+
x=0.8,
|
| 64 |
+
y=1.1,
|
| 65 |
+
orientation='v'
|
| 66 |
+
)
|
| 67 |
+
)
|
| 68 |
+
componente = html.Div([
|
| 69 |
+
html.Label("Accesos a Internet por cada 100 Hogares y Velocidad Media de Bajada", className='title_left'),
|
| 70 |
+
html.Br(),
|
| 71 |
+
dcc.Graph(figure=fig, config={'displayModeBar': False}),
|
| 72 |
+
html.Label("Nota: Los KPIs por PROVINCIA se muestran en los ToolTips", id='pie_pagina_tab3')
|
| 73 |
+
], style={'width': '100%', 'height': '80%'}, id='grafico_barras_tab3')
|
| 74 |
+
return componente
|
components/component_tab3_donuts.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import polars as pl
|
| 2 |
+
import plotly.graph_objects as go
|
| 3 |
+
from dash import html, dcc
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def retorna_pies_tab3(df: pl.DataFrame) -> html.Div:
|
| 7 |
+
"""retorna_pies_tab3: Retorna los Graficos tipo torta del Tablero
|
| 8 |
+
|
| 9 |
+
Args:
|
| 10 |
+
df (pl.DataFrame): Dataframe con la data para generar los gráficos
|
| 11 |
+
|
| 12 |
+
Returns:
|
| 13 |
+
html.Div: Contenedor con los Gráficos tipo barra
|
| 14 |
+
"""
|
| 15 |
+
valores_pie_rangos = [df['Hasta 10 Mbps'].sum(), df['10.01 - 30 Mbps'].sum(),
|
| 16 |
+
df['30.01 - 100 Mbps'].sum(), df['Mayor a 100 Mbps'].sum()]
|
| 17 |
+
valores_tecnologias = [df['ADSL'].sum(), df['CABLEMODEM'].sum(), df['FIBRA'].sum(), df['WIRELESS'].sum()]
|
| 18 |
+
|
| 19 |
+
# Crear gráfico Donut para rangos
|
| 20 |
+
fig_rangos = go.Figure(go.Pie(
|
| 21 |
+
labels=['Hasta 10 Mbps', '10.01 - 30 Mbps', '30.01 - 100 Mbps', 'Mayor a 100 Mbps'],
|
| 22 |
+
values=valores_pie_rangos,
|
| 23 |
+
marker=dict(colors=['#636EFA', '#EF553B', '#00CC96', '#AB63FA']),
|
| 24 |
+
legendgroup='rangos',
|
| 25 |
+
hoverlabel=dict(
|
| 26 |
+
font_size=16,
|
| 27 |
+
font_color="black",
|
| 28 |
+
)
|
| 29 |
+
))
|
| 30 |
+
|
| 31 |
+
fig_rangos.update_layout(
|
| 32 |
+
font=dict(color='#ffffff', size=14),
|
| 33 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 34 |
+
height=230,
|
| 35 |
+
margin=dict(t=20, b=0, l=0, r=20),
|
| 36 |
+
legend=dict(
|
| 37 |
+
title="Rangos",
|
| 38 |
+
yanchor="top",
|
| 39 |
+
y=0.9,
|
| 40 |
+
xanchor="left",
|
| 41 |
+
x=1.0,
|
| 42 |
+
traceorder='normal'
|
| 43 |
+
)
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
# Crear gráfico Donut para tecnologias
|
| 47 |
+
fig_tecnologias = go.Figure(go.Pie(
|
| 48 |
+
labels=['ADSL', 'CABLEMODEM', 'FIBRA', 'WIRELESS'],
|
| 49 |
+
values=valores_tecnologias,
|
| 50 |
+
marker=dict(colors=['#FFA15A', '#19D3F3', '#FF6692', '#B6E880']),
|
| 51 |
+
legendgroup='tecnologias',
|
| 52 |
+
hoverlabel=dict(
|
| 53 |
+
font_size=16,
|
| 54 |
+
font_color="black",
|
| 55 |
+
)
|
| 56 |
+
))
|
| 57 |
+
|
| 58 |
+
fig_tecnologias.update_layout(
|
| 59 |
+
font=dict(color='#ffffff', size=14),
|
| 60 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 61 |
+
height=230,
|
| 62 |
+
margin=dict(t=0, b=0, l=0, r=20),
|
| 63 |
+
legend=dict(
|
| 64 |
+
title="Tecnologías",
|
| 65 |
+
yanchor="top",
|
| 66 |
+
y=0.9,
|
| 67 |
+
xanchor="left",
|
| 68 |
+
x=1.0,
|
| 69 |
+
traceorder='normal'
|
| 70 |
+
)
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
config = {'displayModeBar': False}
|
| 74 |
+
|
| 75 |
+
# Crear los componentes dcc.Graph dentro de un html.Div
|
| 76 |
+
componente_graf_tab3 = html.Div([
|
| 77 |
+
html.Label("Accesos por Rangos de Velocidad y tecnologías", className='title_left'),
|
| 78 |
+
dcc.Graph(figure=fig_rangos, config=config),
|
| 79 |
+
html.Br(),
|
| 80 |
+
html.Br(),
|
| 81 |
+
dcc.Graph(figure=fig_tecnologias, config=config)
|
| 82 |
+
])
|
| 83 |
+
|
| 84 |
+
return componente_graf_tab3
|
components/component_tab3_drop.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html, dcc
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def retorna_tab3_drop(periodos: list) -> html.Div:
|
| 5 |
+
"""retorna_tab3_drop: Retorna el componente Drop del Tablero
|
| 6 |
+
|
| 7 |
+
Args:
|
| 8 |
+
periodos (list): Lista de Periodos a desplegar en el Drop
|
| 9 |
+
|
| 10 |
+
Returns:
|
| 11 |
+
html.Div: Contenedor con el componente Drop
|
| 12 |
+
"""
|
| 13 |
+
component_drop = html.Div([
|
| 14 |
+
# html.Div(html.Label("Accesos Internet"), className='title_left'),
|
| 15 |
+
html.Div(html.Label("Selecciona el Periodo (Trim)"), className='title_left'),
|
| 16 |
+
html.Br(),
|
| 17 |
+
html.Div([
|
| 18 |
+
# html.Div(html.Label("Periodo"), id='label_periodo'),
|
| 19 |
+
dcc.Dropdown(
|
| 20 |
+
id="drop-tab3",
|
| 21 |
+
options=periodos,
|
| 22 |
+
value=periodos[0],
|
| 23 |
+
style={
|
| 24 |
+
"backgroundColor": "#ffffff",
|
| 25 |
+
"fontSize": 18,
|
| 26 |
+
"color": "rgb(51, 51, 51)",
|
| 27 |
+
"border-radius": "1vh",
|
| 28 |
+
},
|
| 29 |
+
),
|
| 30 |
+
], className='one_drop_tab4'),
|
| 31 |
+
|
| 32 |
+
], className='tab_left')
|
| 33 |
+
return component_drop
|
components/component_tab3_tarjetas.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
import polars as pl
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def retorna_tarjetas_tab3(df: pl.DataFrame, accesos: int) -> tuple[html.Div, html.Div, html.Div]:
|
| 6 |
+
"""retorna_tarjetas_tab3: Retorna las 3 tarjetas del Tablero de la visualización
|
| 7 |
+
|
| 8 |
+
Args:
|
| 9 |
+
df (pl.DataFrame): Dataframe con la información de las primeras 2 tarjetas
|
| 10 |
+
accesos (int): Información a Colocar en la Tercera Tarjeta
|
| 11 |
+
|
| 12 |
+
Returns:
|
| 13 |
+
tuple[html.Div, html.Div, html.Div]:
|
| 14 |
+
html.Div: Tarjeta que muestra "Variacion Trimestral Acc 100 Hog"
|
| 15 |
+
html.Div: Tarjeta que muestra "Variacion Trimestral MBPS"
|
| 16 |
+
html.Div: Tarjeta que muestra "Total Accesos Trimestre"
|
| 17 |
+
"""
|
| 18 |
+
tarjeta_1 = html.Div([
|
| 19 |
+
html.Div(html.Label('Variación Trimestral Acc 100 Hog'), className='title_left'),
|
| 20 |
+
html.Br(),
|
| 21 |
+
html.Div(html.Label(f'{df["Crecimiento Accesos 100 Hog"][0]} %'), className='tarjetas')
|
| 22 |
+
], className='contenedor_tarjetas')
|
| 23 |
+
|
| 24 |
+
tarjeta_2 = html.Div([
|
| 25 |
+
html.Div(html.Label('Variación Trimestral MBPS'), className='title_left'),
|
| 26 |
+
html.Br(),
|
| 27 |
+
html.Div(html.Label(f'{df["Crecimineto MBPS Media Bajada"][0]} %'), className='tarjetas')
|
| 28 |
+
], className='contenedor_tarjetas')
|
| 29 |
+
|
| 30 |
+
tarjeta_3 = html.Div([
|
| 31 |
+
html.Div(html.Label('Total Accesos en Trimestre'), className='title_left'),
|
| 32 |
+
html.Br(),
|
| 33 |
+
html.Div(html.Label(f'{accesos:,}'), className='tarjetas')
|
| 34 |
+
], className='contenedor_tarjetas')
|
| 35 |
+
|
| 36 |
+
return (tarjeta_1, tarjeta_2, tarjeta_3)
|
components/component_tab4.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
import plotly.express as px
|
| 3 |
+
import polars as pl
|
| 4 |
+
from components.component_tab4_left import component_tab4_left
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
df_accesos_localidades = pl.read_parquet('data/accesos_localidades_dash.parquet')
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
component_tab_4 = html.Div([
|
| 11 |
+
html.Div([component_tab4_left], className='tab_subcontainers', id='tab4_left'),
|
| 12 |
+
html.Div([], className='tab_subcontainers', id='tab4_center'),
|
| 13 |
+
html.Div([], className='tab_subcontainers', id='tab4_right')
|
| 14 |
+
], className='work_container' , id='tab4_component')
|
components/component_tab4_donuts.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import polars as pl
|
| 2 |
+
import plotly.graph_objects as go
|
| 3 |
+
from dash import html, dcc
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def retorna_graf_tab4(df_pie_rangos: pl.DataFrame, df_tecnologias: pl.DataFrame) -> html.Div:
|
| 7 |
+
"""retorna_graf_tab4: Retorna el contenedor que contiene los Gráficos tipo Tortas de la pestaña
|
| 8 |
+
que muestra el Mapa en la visualizació
|
| 9 |
+
Args:
|
| 10 |
+
df_pie_rangos (pl.DataFrame): Dataframe con la data para el gráfico de Rangos de Velocidades
|
| 11 |
+
df_tecnologias (pl.DataFrame): Dataframe con la data pata el gráfico de las tecnologías
|
| 12 |
+
|
| 13 |
+
Returns:
|
| 14 |
+
html.Div: contenedor con los gráficos tipo torta
|
| 15 |
+
"""
|
| 16 |
+
# Convertir columnas a listas de valores
|
| 17 |
+
valores_pie_rangos = [df_pie_rangos[0, i] for i in range(len(df_pie_rangos.columns))]
|
| 18 |
+
valores_tecnologias = [df_tecnologias[0, i] for i in range(len(df_tecnologias.columns))]
|
| 19 |
+
|
| 20 |
+
# Crear gráfico Donut para df_pie_rangos
|
| 21 |
+
fig_rangos = go.Figure(go.Pie(
|
| 22 |
+
labels=df_pie_rangos.columns,
|
| 23 |
+
values=valores_pie_rangos,
|
| 24 |
+
marker=dict(colors=['#636EFA', '#EF553B', '#00CC96', '#AB63FA']),
|
| 25 |
+
legendgroup='rangos',
|
| 26 |
+
hoverlabel=dict(
|
| 27 |
+
font_size=16,
|
| 28 |
+
font_color="black",
|
| 29 |
+
)
|
| 30 |
+
))
|
| 31 |
+
|
| 32 |
+
fig_rangos.update_layout(
|
| 33 |
+
font=dict(color='#ffffff', size=16),
|
| 34 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 35 |
+
height=270,
|
| 36 |
+
margin=dict(t=0, b=0, l=0, r=0),
|
| 37 |
+
legend=dict(
|
| 38 |
+
title='Rangos',
|
| 39 |
+
yanchor="top",
|
| 40 |
+
y=0.7,
|
| 41 |
+
xanchor="left",
|
| 42 |
+
x=0.9,
|
| 43 |
+
traceorder='normal'
|
| 44 |
+
)
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
# Crear gráfico Donut para df_tecnologias
|
| 48 |
+
fig_tecnologias = go.Figure(go.Pie(
|
| 49 |
+
labels=df_tecnologias.columns,
|
| 50 |
+
values=valores_tecnologias,
|
| 51 |
+
marker=dict(colors=['#FFA15A', '#19D3F3', '#FF6692', '#B6E880']),
|
| 52 |
+
legendgroup='tecnologias',
|
| 53 |
+
hoverlabel=dict(
|
| 54 |
+
font_size=16,
|
| 55 |
+
font_color="black",
|
| 56 |
+
)
|
| 57 |
+
))
|
| 58 |
+
|
| 59 |
+
fig_tecnologias.update_layout(
|
| 60 |
+
font=dict(color='#ffffff', size=16),
|
| 61 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
| 62 |
+
height=270,
|
| 63 |
+
margin=dict(t=0, b=0, l=0, r=0),
|
| 64 |
+
legend=dict(
|
| 65 |
+
title="Tecnologías",
|
| 66 |
+
yanchor="top",
|
| 67 |
+
y=0.7,
|
| 68 |
+
xanchor="left",
|
| 69 |
+
x=1.0,
|
| 70 |
+
traceorder='normal'
|
| 71 |
+
)
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
config = {'displayModeBar': False}
|
| 75 |
+
|
| 76 |
+
# Crear los componentes dcc.Graph dentro de un html.Div
|
| 77 |
+
componente_graf_tab4 = html.Div([
|
| 78 |
+
html.Label("Accesos por Rangos de Velocidad y tecnologías", className='title_left'),
|
| 79 |
+
html.Br(),
|
| 80 |
+
html.Br(),
|
| 81 |
+
html.Br(),
|
| 82 |
+
dcc.Graph(figure=fig_rangos, config=config),
|
| 83 |
+
html.Br(),
|
| 84 |
+
dcc.Graph(figure=fig_tecnologias, config=config)
|
| 85 |
+
], id='contenedor_pies_tab4')
|
| 86 |
+
|
| 87 |
+
return componente_graf_tab4
|
components/component_tab4_left.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html, dcc
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
minimos = [2000, 5000, 10000, 20000, 50000, 100000, 500000]
|
| 5 |
+
maximos = [5000, 10000, 20000, 50000, 100000, 500000, 3000000]
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
component_tab4_left = html.Div([
|
| 9 |
+
dcc.Store(id="store_tab4", data={"btn_tab4": 0}),
|
| 10 |
+
html.Div(html.Label("Rango Habitantes"), className='title_left'),
|
| 11 |
+
html.Br(),
|
| 12 |
+
html.Div([
|
| 13 |
+
html.Label("Minimo"),
|
| 14 |
+
dcc.Dropdown(
|
| 15 |
+
id="drop-minimo_tab4",
|
| 16 |
+
options=minimos,
|
| 17 |
+
value=minimos[0],
|
| 18 |
+
style={
|
| 19 |
+
"backgroundColor": "#ffffff",
|
| 20 |
+
"fontSize": 14,
|
| 21 |
+
"color": "rgb(51, 51, 51)",
|
| 22 |
+
"border-radius": "1vh",
|
| 23 |
+
},
|
| 24 |
+
),
|
| 25 |
+
], className='one_drop_tab4'),
|
| 26 |
+
html.Br(),
|
| 27 |
+
html.Div([
|
| 28 |
+
html.Label("Máximo"),
|
| 29 |
+
dcc.Dropdown(
|
| 30 |
+
id="drop-maximo_tab4",
|
| 31 |
+
options=maximos,
|
| 32 |
+
value=maximos[0],
|
| 33 |
+
style={
|
| 34 |
+
# "backgroundColor": "#70cbff",
|
| 35 |
+
"backgroundColor": "#ffffff",
|
| 36 |
+
"fontSize": 14,
|
| 37 |
+
"color": "rgb(51, 51, 51)",
|
| 38 |
+
"border-radius": "1vh",
|
| 39 |
+
},
|
| 40 |
+
),
|
| 41 |
+
], className='one_drop_tab4'),
|
| 42 |
+
html.Br(),
|
| 43 |
+
html.Br(),
|
| 44 |
+
html.Div(
|
| 45 |
+
html.Button("Ok", className="btns", id="btn_tab4"),
|
| 46 |
+
className="btn-container",
|
| 47 |
+
id="btn_container_tab4",
|
| 48 |
+
),
|
| 49 |
+
html.Br(),
|
| 50 |
+
html.Div([], id='tab4_rangos_response'),
|
| 51 |
+
html.Br(),
|
| 52 |
+
# html.Br(),
|
| 53 |
+
html.Div([], id='tab4_texto_resultados')
|
| 54 |
+
], className='tab_left')
|
components/component_tab4_mapa.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import dcc
|
| 2 |
+
import plotly.express as px
|
| 3 |
+
import polars as pl
|
| 4 |
+
import pandas as pd
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def retorna_mapa(df: pl.DataFrame) -> dcc.Graph:
|
| 8 |
+
"""retorna_mapa: Retorna el componente del Mapa de la visualizacion
|
| 9 |
+
|
| 10 |
+
Args:
|
| 11 |
+
df (pl.DataFrame): Dataframe con la data necesaria para el mapa
|
| 12 |
+
|
| 13 |
+
Returns:
|
| 14 |
+
dcc.Graph: Componente Grafico que encapsula al mapa
|
| 15 |
+
"""
|
| 16 |
+
df = df.to_pandas()
|
| 17 |
+
|
| 18 |
+
# rangos de la población
|
| 19 |
+
bins = [2000, 5000, 10000, 20000, 50000, 100000, 500000, 10000000]
|
| 20 |
+
labels = [
|
| 21 |
+
'2.000-5.000 Hab',
|
| 22 |
+
'5.001-10.000 Hab',
|
| 23 |
+
'10.001-20.000 Hab',
|
| 24 |
+
'20.001-50.000 Hab',
|
| 25 |
+
'50.001-100.000 Hab',
|
| 26 |
+
'100.001-500.000 Hab',
|
| 27 |
+
'Más de 500.000 Hab'
|
| 28 |
+
]
|
| 29 |
+
df['Rango'] = pd.cut(df['Población'], bins=bins, labels=labels)
|
| 30 |
+
|
| 31 |
+
# Ajustando para que todas las burbujas sean del mismo tamaño
|
| 32 |
+
size_map = {
|
| 33 |
+
'2.000-5.000 Hab': 0.01,
|
| 34 |
+
'5.001-10.000 Hab': 0.01,
|
| 35 |
+
'10.001-20.000 Hab': 0.01,
|
| 36 |
+
'20.001-50.000 Hab': 0.01,
|
| 37 |
+
'50.001-100.000 Hab': 0.01,
|
| 38 |
+
'100.001-500.000 Hab': 0.01,
|
| 39 |
+
'Más de 500.000 Hab': 0.01,
|
| 40 |
+
}
|
| 41 |
+
# Estableciendo los colores por Region que sean Fijos (siempre los mismos)
|
| 42 |
+
color_map = {
|
| 43 |
+
'2.000-5.000 Hab': '#1f77b4',
|
| 44 |
+
'5.001-10.000 Hab': '#ff7f0e',
|
| 45 |
+
'10.001-20.000 Hab': '#2ca02c',
|
| 46 |
+
'20.001-50.000 Hab': '#d62728',
|
| 47 |
+
'50.001-100.000 Hab': '#9467bd',
|
| 48 |
+
'100.001-500.000 Hab': '#8c564b',
|
| 49 |
+
'Más de 500.000 Hab': '#e377c2'
|
| 50 |
+
}
|
| 51 |
+
df['Size'] = df['Rango'].map(size_map)
|
| 52 |
+
df['Size'] = 0.01
|
| 53 |
+
df['Color'] = df['Rango'].map(color_map)
|
| 54 |
+
|
| 55 |
+
fig = px.scatter_mapbox(
|
| 56 |
+
df,
|
| 57 |
+
lat="Latitud",
|
| 58 |
+
lon="Longitud",
|
| 59 |
+
hover_name="Localidad",
|
| 60 |
+
hover_data={"Provincia": True, "Partido": True, "Población": True, "Accesos 100 Hab": True,
|
| 61 |
+
"Size": False, "Rango": False, "Latitud": False, "Longitud": False},
|
| 62 |
+
size="Size",
|
| 63 |
+
size_max=5,
|
| 64 |
+
color="Rango",
|
| 65 |
+
color_discrete_map=color_map,
|
| 66 |
+
category_orders={"Rango": labels},
|
| 67 |
+
zoom=3.5,
|
| 68 |
+
height=660
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
# Estilo del Mapa
|
| 72 |
+
fig.update_layout(mapbox_style="carto-darkmatter")
|
| 73 |
+
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
|
| 74 |
+
fig.update_layout(mapbox=dict(center=dict(lat=-38.4161, lon=-63.6167), zoom=3.5))
|
| 75 |
+
|
| 76 |
+
fig.update_layout(
|
| 77 |
+
legend=dict(
|
| 78 |
+
title="Rango de Población",
|
| 79 |
+
x=0.60,
|
| 80 |
+
y=0.08,
|
| 81 |
+
traceorder="normal",
|
| 82 |
+
font=dict(color="#ffffff"),
|
| 83 |
+
bgcolor='rgba(0,0,0,0)'
|
| 84 |
+
)
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
fig.update_layout(
|
| 88 |
+
hoverlabel=dict(
|
| 89 |
+
font_size=18,
|
| 90 |
+
font_color="white",
|
| 91 |
+
)
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
fig.update_layout(clickmode='event+select')
|
| 95 |
+
|
| 96 |
+
fig.update_layout(mapbox_zoom=3.5)
|
| 97 |
+
config = {'displayModeBar': False}
|
| 98 |
+
mapa = dcc.Graph(id='mapa', figure=fig, config=config)
|
| 99 |
+
return mapa
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
'''
|
| 103 |
+
“open-street-map”: El estilo Inicial SI CORRE
|
| 104 |
+
“carto-positron”: Un estilo claro y minimalista. SI CORRE
|
| 105 |
+
“carto-darkmatter”: Un estilo oscuro y minimalista. SI CORRE
|
| 106 |
+
“stamen-terrain”: Un estilo que resalta el terreno. NO CORRE
|
| 107 |
+
“stamen-toner”: Un estilo en blanco y negro con líneas claras. NO CORRE
|
| 108 |
+
“stamen-watercolor”: Un estilo artístico que parece pintado con acuarelas. NO CORRE
|
| 109 |
+
“basic”: Un estilo básico y limpio. NO CORRE
|
| 110 |
+
“streets”: Un estilo que resalta las calles. NO CORRE
|
| 111 |
+
“outdoors”: Un estilo que resalta las áreas al aire libre. NO CORRE
|
| 112 |
+
“light”: Un estilo claro.
|
| 113 |
+
“dark”: Un estilo oscuro. No corre
|
| 114 |
+
“satellite”: Un estilo de imagen satelital. NO CORRE
|
| 115 |
+
“satellite-streets”: Imagen satelital con calles resaltadas. NO CORRE
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
'''
|
components/component_tab4_retorna_texto.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import html
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def retorna_tab4_texto_resultado(
|
| 5 |
+
total_poblacion: int, total_localidades: int, total_accesos: int
|
| 6 |
+
) -> html.Div:
|
| 7 |
+
"""retorna_tab4_texto_resultado: Retorna la informacion tipo texto que se muestra en la parte
|
| 8 |
+
izquierda en la pestaña del mapa
|
| 9 |
+
|
| 10 |
+
Args:
|
| 11 |
+
total_poblacion (int): Número de habitantes en el Rango de habitantes escogido
|
| 12 |
+
total_localidades (int): Número de localidades en el Rango de habitantes escogido
|
| 13 |
+
total_accesos (int): Número de accesos a internet en el Rango de habitantes escogido
|
| 14 |
+
|
| 15 |
+
Returns:
|
| 16 |
+
html.Div: Contenedor con la Información tipo texto mostrada en la pestaña del Mapa
|
| 17 |
+
"""
|
| 18 |
+
accesos_100_hab = round(100 * (total_accesos / total_poblacion), 2)
|
| 19 |
+
component = html.Div([
|
| 20 |
+
html.Div(html.Label('Datos de Valor'), className='title_left'),
|
| 21 |
+
html.Br(),
|
| 22 |
+
html.Label('Localidades del Rango'),
|
| 23 |
+
html.Br(),
|
| 24 |
+
html.Label(f"{total_localidades:,}"),
|
| 25 |
+
html.Br(),
|
| 26 |
+
html.Br(),
|
| 27 |
+
html.Label('Población del Rango'),
|
| 28 |
+
html.Br(),
|
| 29 |
+
html.Label(f"{total_poblacion:,}"),
|
| 30 |
+
html.Br(),
|
| 31 |
+
html.Br(),
|
| 32 |
+
html.Label('Total Accesos en Rango'),
|
| 33 |
+
html.Br(),
|
| 34 |
+
html.Label(f"{total_accesos:,}"),
|
| 35 |
+
html.Br(),
|
| 36 |
+
html.Br(),
|
| 37 |
+
html.Label('Accesos Cada 100 Hab'),
|
| 38 |
+
html.Br(),
|
| 39 |
+
html.Label(accesos_100_hab)
|
| 40 |
+
], id='texto_tab4')
|
| 41 |
+
return component
|
data/EDA_internet_rangos.parquet
ADDED
|
Binary file (10.3 kB). View file
|
|
|
data/EDA_internet_tecnologias.parquet
ADDED
|
Binary file (13.4 kB). View file
|
|
|
data/accesos_localidades_dash.parquet
ADDED
|
Binary file (140 kB). View file
|
|
|
data/data_tablero_dashboard.parquet
ADDED
|
Binary file (50.8 kB). View file
|
|
|
data/df_pie_tab2.parquet
ADDED
|
Binary file (2.12 kB). View file
|
|
|
data/internet_tab2.parquet
ADDED
|
Binary file (7.48 kB). View file
|
|
|
data/rangos_internet_graficos_tab2 copy.parquet
ADDED
|
Binary file (2.59 kB). View file
|
|
|
data/rangos_internet_graficos_tab2.parquet
ADDED
|
Binary file (2.59 kB). View file
|
|
|
data/rangos_localidades.parquet
ADDED
|
Binary file (77.8 kB). View file
|
|
|
data/tarjetas.parquet
ADDED
|
Binary file (6.57 kB). View file
|
|
|
data/tecnologias_internet_graficos_tab2 copy.parquet
ADDED
|
Binary file (2.97 kB). View file
|
|
|
data/tecnologias_internet_graficos_tab2.parquet
ADDED
|
Binary file (2.97 kB). View file
|
|
|
data/telefonia_fija_tab2.parquet
ADDED
|
Binary file (8.9 kB). View file
|
|
|
data/telefonia_movil_tab2.parquet
ADDED
|
Binary file (12.1 kB). View file
|
|
|
data/television_tab2.parquet
ADDED
|
Binary file (12.3 kB). View file
|
|
|
main.py
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dash import Dash, dcc, html, Input, Output, callback, State
|
| 2 |
+
import polars as pl
|
| 3 |
+
from utils.retorna_dfs_grfaicos_tab4 import retorna_dfs_graficos_tab4
|
| 4 |
+
from components.component_home import component_home
|
| 5 |
+
from components.component_tab2 import component_tab_2
|
| 6 |
+
from components.component_tab2_textos import textos_left_tab2
|
| 7 |
+
from components.component_tab2_grafico import retorna_grafico_tab2
|
| 8 |
+
from components.component_tab3 import retorna_tab3
|
| 9 |
+
from components.component_tab3_tarjetas import retorna_tarjetas_tab3
|
| 10 |
+
from components.component_tab3_barras import retorna_barras_tab3
|
| 11 |
+
from components.component_tab3_donuts import retorna_pies_tab3
|
| 12 |
+
from components.component_tab4 import component_tab_4
|
| 13 |
+
from components.component_tab4_mapa import retorna_mapa
|
| 14 |
+
from components.component_tab4_donuts import retorna_graf_tab4
|
| 15 |
+
from components.component_tab4_retorna_texto import retorna_tab4_texto_resultado
|
| 16 |
+
|
| 17 |
+
accesos_localidades = pl.read_parquet('data/accesos_localidades_dash.parquet')
|
| 18 |
+
rangos_localidades = pl.read_parquet('data/rangos_localidades.parquet')
|
| 19 |
+
data_tablero = pl.read_parquet('data/data_tablero_dashboard.parquet')
|
| 20 |
+
tarjetas = pl.read_parquet('data/tarjetas.parquet')
|
| 21 |
+
lista_periodos = data_tablero['Periodo Tablero'].unique().to_list()
|
| 22 |
+
lista_periodos.sort()
|
| 23 |
+
lista_periodos = [item[7:] for item in lista_periodos]
|
| 24 |
+
periodos_dashboard = lista_periodos.copy()
|
| 25 |
+
periodos_dashboard.pop(0)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
app = Dash(
|
| 29 |
+
__name__,
|
| 30 |
+
suppress_callback_exceptions=True,
|
| 31 |
+
title="Telecomunicaciones Argentina",
|
| 32 |
+
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
tabs_styles = {"height": "2em", "marginLeft": "0.5em", "marginRight": "1.5em"}
|
| 37 |
+
tab_style = {
|
| 38 |
+
"border": "1px solid #656565",
|
| 39 |
+
"color": "#d0d0d0",
|
| 40 |
+
"backgroundColor": "#2b2b2b",
|
| 41 |
+
"padding": "0.5em",
|
| 42 |
+
"fontWeight": "bold",
|
| 43 |
+
"fontSize": "0.9em",
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
tab_selected_style = {
|
| 47 |
+
"borderTop": "1px solid #ffffff",
|
| 48 |
+
"borderLeft": "1px solid #656565",
|
| 49 |
+
"borderRight": "1px solid #656565",
|
| 50 |
+
"backgroundColor": "#2b2b2b",
|
| 51 |
+
"color": "#ffffff",
|
| 52 |
+
"padding": "0.5em",
|
| 53 |
+
"fontSize": "1.1em",
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
app.layout = html.Div(
|
| 57 |
+
[
|
| 58 |
+
dcc.Tabs(
|
| 59 |
+
id="tabs-inline",
|
| 60 |
+
value="tab-1",
|
| 61 |
+
children=[
|
| 62 |
+
dcc.Tab(
|
| 63 |
+
label="Home",
|
| 64 |
+
value="tab-1",
|
| 65 |
+
style=tab_style,
|
| 66 |
+
selected_style=tab_selected_style,
|
| 67 |
+
),
|
| 68 |
+
dcc.Tab(
|
| 69 |
+
label="¿Porqué Internet?",
|
| 70 |
+
value="tab-2",
|
| 71 |
+
style=tab_style,
|
| 72 |
+
selected_style=tab_selected_style,
|
| 73 |
+
),
|
| 74 |
+
dcc.Tab(
|
| 75 |
+
label="Seguimiento a Métricas",
|
| 76 |
+
value="tab-3",
|
| 77 |
+
style=tab_style,
|
| 78 |
+
selected_style=tab_selected_style,
|
| 79 |
+
),
|
| 80 |
+
dcc.Tab(
|
| 81 |
+
label="Mapa de Oportunidades",
|
| 82 |
+
value="tab-4",
|
| 83 |
+
style=tab_style,
|
| 84 |
+
selected_style=tab_selected_style,
|
| 85 |
+
),
|
| 86 |
+
],
|
| 87 |
+
style=tabs_styles,
|
| 88 |
+
),
|
| 89 |
+
html.Div(id="tabs-content-inline-3"),
|
| 90 |
+
]
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@callback(Output("tabs-content-inline-3", "children"), Input("tabs-inline", "value"))
|
| 95 |
+
def render_content(tab):
|
| 96 |
+
if tab == "tab-1":
|
| 97 |
+
return component_home
|
| 98 |
+
elif tab == "tab-2":
|
| 99 |
+
return component_tab_2
|
| 100 |
+
elif tab == "tab-3":
|
| 101 |
+
return retorna_tab3(periodos=periodos_dashboard)
|
| 102 |
+
elif tab == "tab-4":
|
| 103 |
+
return component_tab_4
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
@app.callback(
|
| 107 |
+
Output('tab4_rangos_response', 'children'),
|
| 108 |
+
Output('tab4_center', 'children'),
|
| 109 |
+
Output('tab4_right', 'children'),
|
| 110 |
+
Output('tab4_texto_resultados', 'children'),
|
| 111 |
+
Output("store_tab4", "data"),
|
| 112 |
+
Input('btn_tab4', 'n_clicks'),
|
| 113 |
+
Input('drop-minimo_tab4', 'value'),
|
| 114 |
+
Input('drop-maximo_tab4', 'value'),
|
| 115 |
+
State("store_tab4", "data"),
|
| 116 |
+
prevent_initial_call=True,
|
| 117 |
+
)
|
| 118 |
+
def update_tab_4(n_clicks: int, min_value: int, max_value: int, data: dict
|
| 119 |
+
) -> tuple[html.Label | html.Br, html.Div | None , html.Div | None, html.Div | None, dict]:
|
| 120 |
+
"""update_tab_4: Actualiza los componentes de La Pestaña 4 o "Mapa de Oportunidades"
|
| 121 |
+
|
| 122 |
+
Args:
|
| 123 |
+
n_clicks (int): Numero de Veces que se le ha dado click al boton del tab 4
|
| 124 |
+
min_value (int): Valor seleccionado por el Usuario, capturado por un componente dcc.Drop (mínimo población)
|
| 125 |
+
max_value (int): Valor seleccionado por el Usuario, capturado por un componente dcc.Drop (máximo población)
|
| 126 |
+
data (dict): Banco de Datos tipo dcc.Store. pertenece al componente con el id="store_tab4" en el archivo
|
| 127 |
+
component_tab4_left.py Utilizado para llevar un paralelo de cuantas veces an clickleado el boton
|
| 128 |
+
|
| 129 |
+
Returns:
|
| 130 |
+
tuple[html.Label|html.Br, html.Div|None , html.Div|None, html.Div|None, dict]:
|
| 131 |
+
html.Label|html.Br: Label cuando se selecciona mal un rango, Br cuando es correcto el rango
|
| 132 |
+
html.Div|None : Componente que tiene el Mapa de la Tab 4
|
| 133 |
+
html.Div|None: Componente que contiene los dos graficos tipo pies de la tab 4
|
| 134 |
+
html.Div|None: Componente de Texto que se muestra en la parte izquierda de la pestaña
|
| 135 |
+
Tab_4 donde se dice Numero de Localidades, cantidad de Hab, etc
|
| 136 |
+
dict: Banco de Datos dcc.Store con id="store_tab4"
|
| 137 |
+
"""
|
| 138 |
+
btn_tab4 = data.get("btn_tab4")
|
| 139 |
+
if not n_clicks or n_clicks == btn_tab4:
|
| 140 |
+
return (html.Br(), None, None, None, data)
|
| 141 |
+
if n_clicks > btn_tab4:
|
| 142 |
+
btn_tab4 += 1
|
| 143 |
+
data["btn_tab4"] = btn_tab4
|
| 144 |
+
if max_value > min_value:
|
| 145 |
+
response = html.Br()
|
| 146 |
+
df_mapa, df_pie_rangos, df_tecnologias, n_accesos, n_localidades = retorna_dfs_graficos_tab4(
|
| 147 |
+
df_accesos_localidades=accesos_localidades,
|
| 148 |
+
df_rangos=rangos_localidades,
|
| 149 |
+
hab_minimo=min_value,
|
| 150 |
+
hab_maximo=max_value
|
| 151 |
+
)
|
| 152 |
+
poblacion_total_rango = df_mapa['Población'].sum()
|
| 153 |
+
componente_texto = retorna_tab4_texto_resultado(
|
| 154 |
+
total_poblacion=poblacion_total_rango,
|
| 155 |
+
total_localidades=n_localidades,
|
| 156 |
+
total_accesos=n_accesos
|
| 157 |
+
)
|
| 158 |
+
mapa = retorna_mapa(df=df_mapa)
|
| 159 |
+
graficos_tab4 = retorna_graf_tab4(
|
| 160 |
+
df_pie_rangos=df_pie_rangos,
|
| 161 |
+
df_tecnologias=df_tecnologias['ADSL', 'CABLEMODEM', 'FIBRA', 'WIRELESS']
|
| 162 |
+
)
|
| 163 |
+
else:
|
| 164 |
+
response = html.Label('Rango no Permitido !!!')
|
| 165 |
+
mapa = None
|
| 166 |
+
graficos_tab4 = None
|
| 167 |
+
componente_texto = None
|
| 168 |
+
return (response, mapa, graficos_tab4, componente_texto, data)
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
@callback(
|
| 172 |
+
Output('title_right_tab2', 'children'),
|
| 173 |
+
Output('grafico_right_tab2', 'children'),
|
| 174 |
+
Output('texto_tab2', 'children'),
|
| 175 |
+
Input('control_slides_tab2', 'value'),
|
| 176 |
+
prevent_initial_call=True,
|
| 177 |
+
)
|
| 178 |
+
def update_tab_2(value: int) -> tuple[str | None, html.Div | None, html.Div | None]:
|
| 179 |
+
"""update_tab_2: Se encarga de actualizar los componentes de la pesataña Tab2 o "¿Porque Internet?
|
| 180 |
+
|
| 181 |
+
Args:
|
| 182 |
+
value (int): Valor que se recibe del componente daq.NumericInput del archivo
|
| 183 |
+
component_tab2_left.py
|
| 184 |
+
|
| 185 |
+
Returns:
|
| 186 |
+
tuple[str|None, html.Div|None, html.Div|None]:
|
| 187 |
+
str|None: Título de la Diapositiva en la Tab 2 o "¿Porque Internet?
|
| 188 |
+
html.Div|None: Diapositiva (Gráfico) en la Tab 2 o "¿Porque Internet?
|
| 189 |
+
html.Div|None: Texto que se muestra en la parte izquierda de la pantalla
|
| 190 |
+
en la Tab 2 o "¿Porque Internet?
|
| 191 |
+
"""
|
| 192 |
+
titulos_diapositivas = [
|
| 193 |
+
'Ingresos en Miles de Pesos Argentinos',
|
| 194 |
+
'Ingresos en Miles de Dolares',
|
| 195 |
+
'Comparación de Ingresos en Dolares por Tecnología',
|
| 196 |
+
'Accesos por cada 100 Habitantes',
|
| 197 |
+
'Accesos de Telefonía Movil',
|
| 198 |
+
'Cantidad de Llamadas Telefonía Movil',
|
| 199 |
+
'Cantidad de Minutos Consumidos Telefonía Movil',
|
| 200 |
+
'Evolución en Accesos e Ingresos en la última Decada',
|
| 201 |
+
'Evolución de los Accesos de las Tecnologías para el Acceso a Internet',
|
| 202 |
+
'Evolución de los Accesos a Internet en los Distintos Rangos de Velocidad',
|
| 203 |
+
]
|
| 204 |
+
if value in range(1, 11):
|
| 205 |
+
componente = retorna_grafico_tab2(numero_graf=value)
|
| 206 |
+
title = html.Label(titulos_diapositivas[value - 1])
|
| 207 |
+
texto = textos_left_tab2[value - 1] if value in [1, 2, 3, 4, 7, 8, 9, 10] else None
|
| 208 |
+
return (title, componente, texto)
|
| 209 |
+
else:
|
| 210 |
+
return (None, None, None)
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
@app.callback(
|
| 214 |
+
Output('tarjeta_1', 'children'),
|
| 215 |
+
Output('tarjeta_2', 'children'),
|
| 216 |
+
Output('tarjeta_3', 'children'),
|
| 217 |
+
Output('barras_tab3', 'children'),
|
| 218 |
+
Output('pies_tab3', 'children'),
|
| 219 |
+
Input('drop-tab3', 'value'),
|
| 220 |
+
)
|
| 221 |
+
def update_tab_3(value: str) -> tuple[html.Div, html.Div, html.Div, html.Div, html.Div]:
|
| 222 |
+
"""update_tab_3: Se encarga de actualizar los componentes de la Tab 3 o "Seguimiento a Métricas"
|
| 223 |
+
|
| 224 |
+
Args:
|
| 225 |
+
value (str): Periodo Seleccionado por el Usuario en la Pestaña del Tablero
|
| 226 |
+
|
| 227 |
+
Returns:
|
| 228 |
+
tuple[html.Div, html.Div, html.Div, html.Div, html.Div]:
|
| 229 |
+
html.Div: Componente que se Ubica en la tarjeta Variacion Trimestral Accesos 100 Hog
|
| 230 |
+
html.Div: Componente que se Ubica en la tarjeta Variacion Trimestral MBPS
|
| 231 |
+
html.Div: Componente que se Ubica en la tarjeta Total Accesos en Trimestre
|
| 232 |
+
html.Div: Componente con el Grafico de Barras del Tablero
|
| 233 |
+
html.Div Componente con los dos Graficos tipo Pie del tablero
|
| 234 |
+
"""
|
| 235 |
+
mask = data_tablero['Periodo'] == value
|
| 236 |
+
df = data_tablero.filter(mask)
|
| 237 |
+
barras = retorna_barras_tab3(df=df)
|
| 238 |
+
pies = retorna_pies_tab3(df=df)
|
| 239 |
+
mask = tarjetas['Periodo'] == value
|
| 240 |
+
df_tarjetas = tarjetas.filter(mask)
|
| 241 |
+
tarjeta_1, tarjeta_2, tarjeta_3 = retorna_tarjetas_tab3(df=df_tarjetas, accesos=df['Total Accesos'].sum())
|
| 242 |
+
return (tarjeta_1, tarjeta_2, tarjeta_3, barras, pies)
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
if __name__ == "__main__":
|
| 246 |
+
app.run(debug=False)
|
requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
dash==2.16.1
|
| 2 |
+
dash_daq==0.5.0
|
| 3 |
+
pandas==2.2.2
|
| 4 |
+
plotly==5.21.0
|
| 5 |
+
polars==1.2.1
|
| 6 |
+
pyarrow==17.0.0
|
utils/retorna_dfs_grfaicos_tab4.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import polars as pl
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def retorna_dfs_graficos_tab4(
|
| 5 |
+
df_accesos_localidades: pl.DataFrame,
|
| 6 |
+
df_rangos: pl.DataFrame,
|
| 7 |
+
hab_minimo: int,
|
| 8 |
+
hab_maximo: int) -> tuple[pl.DataFrame, pl.DataFrame, pl.DataFrame, int, int]:
|
| 9 |
+
"""retorna_dfs_graficos_tab4: Es llamada desde la Callback que actualiza el TAB 4 o
|
| 10 |
+
'Mapa de Oportunidades` en la visualización. Se encarga de preparar la
|
| 11 |
+
data para los distintos componentes de esa pestaña de la visualización
|
| 12 |
+
|
| 13 |
+
Args:
|
| 14 |
+
df_accesos_localidades (pl.DataFrame): Dataframe con la Data de todas las localidades
|
| 15 |
+
df_rangos (pl.DataFrame): Dataframe con la data de los Rangos de Velocidad asociados a las localidades
|
| 16 |
+
hab_minimo (int): Rango inferior de habitantes selecionado por el usuario
|
| 17 |
+
hab_maximo (int): Rango superior de Habitantes selecionado por el usuario
|
| 18 |
+
|
| 19 |
+
Returns:
|
| 20 |
+
tuple[pl.DataFrame,pl.DataFrame, pl.DataFrame, int, int]:
|
| 21 |
+
df_mapa: Dataframe con información de localidades seleccionadas con sus latitudes y longitudes
|
| 22 |
+
e informacion para el tooltip
|
| 23 |
+
df_pie_rangos: Dataframe que va dirigido a alimentar el Grafico de Pie de Rango de Velocidades
|
| 24 |
+
df_tecnologias: Dataframe que va dirigido a alimentar el Grafico de Pies de las Tecnologias
|
| 25 |
+
total_accesos: Dato que se muestra en la Seccion Izquierda de la pestaña, donde se muestra texto
|
| 26 |
+
total_localidades:Dato que se muestra en la Seccion Izquierda de la pestaña, donde se muestra texto
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
"""
|
| 31 |
+
'''Obteniendo la Data que va para el Mapa, df_mapa'''
|
| 32 |
+
mask = (df_accesos_localidades['Población'] >= hab_minimo) &\
|
| 33 |
+
(df_accesos_localidades['Población'] <= hab_maximo)
|
| 34 |
+
|
| 35 |
+
# Esta lista de Localidades (en el rango de poblacion) la utilizaré para filtrar en el
|
| 36 |
+
# dataframe de rangos de velocidades
|
| 37 |
+
lista_ids_localidades = df_accesos_localidades.filter(mask)['id_localidad'].to_list()
|
| 38 |
+
total_localidades = len(lista_ids_localidades)
|
| 39 |
+
|
| 40 |
+
columns = ['Provincia', 'Partido', 'Localidad', 'Población', 'Accesos 100 Hab', 'Longitud', 'Latitud']
|
| 41 |
+
df_mapa = df_accesos_localidades.filter(mask)[columns]
|
| 42 |
+
|
| 43 |
+
'''Obteniendo la Data para el grafico que clasifica por tipo de Tecnologia'''
|
| 44 |
+
df_tecnologias = pl.DataFrame()
|
| 45 |
+
adsl = df_accesos_localidades.filter(mask)['ADSL'].sum()
|
| 46 |
+
cable_modem = df_accesos_localidades.filter(mask)['CABLEMODEM'].sum()
|
| 47 |
+
fibra = df_accesos_localidades.filter(mask)['FIBRA'].sum()
|
| 48 |
+
wireless = df_accesos_localidades.filter(mask)['WIRELESS'].sum()
|
| 49 |
+
satelital = df_accesos_localidades.filter(mask)['SATELITAL'].sum()
|
| 50 |
+
winmax = df_accesos_localidades.filter(mask)['WINMAX'].sum()
|
| 51 |
+
tecnologias = [adsl, cable_modem, fibra, wireless, satelital, winmax]
|
| 52 |
+
columns = ['ADSL', 'CABLEMODEM', 'FIBRA', 'WIRELESS', 'SATELITAL', 'WINMAX']
|
| 53 |
+
for i in range(6):
|
| 54 |
+
df_tecnologias = df_tecnologias.with_columns(pl.lit(tecnologias[i]).alias(columns[i]))
|
| 55 |
+
|
| 56 |
+
'''Obteniendo la Data que va para el Pie con Rangos de Velocidades, df_pie_rangos'''
|
| 57 |
+
df_pie_rangos = pl.DataFrame()
|
| 58 |
+
rangos = ['Hasta 10 Mbps', '10.01 - 30 Mbps', '30.01 - 100 Mbps', 'Mayor a 100 Mbps']
|
| 59 |
+
velocidades = [(0, 10), (10.01, 30), (30.01, 100), (100.01, 1000000)]
|
| 60 |
+
|
| 61 |
+
total_accesos = 0
|
| 62 |
+
for i in range(4):
|
| 63 |
+
menor = velocidades[i][0]
|
| 64 |
+
mayor = velocidades[i][1]
|
| 65 |
+
mask = (df_rangos['id_localidad'].is_in(lista_ids_localidades)) &\
|
| 66 |
+
(df_rangos['velocidad_mbps'].is_between(menor, mayor))
|
| 67 |
+
accesos = df_rangos.filter(mask)['accesos'].sum()
|
| 68 |
+
total_accesos += accesos
|
| 69 |
+
df_pie_rangos = df_pie_rangos.with_columns(pl.lit(accesos).alias(rangos[i]))
|
| 70 |
+
|
| 71 |
+
return (df_mapa, df_pie_rangos, df_tecnologias, total_accesos, total_localidades)
|