Invita a la autocomplacencia
Un sobresaliente provincial transmite que todo funciona y que no hace falta actuar
Turismo, territorio, Google Cloud e IA en Málaga
Un sobresaliente provincial transmite que todo funciona y que no hace falta actuar
Mezcla la cala tranquila por la mañana con la calle saturada de madrugada
Una media global no indica dónde reforzar limpieza, movilidad o descanso
Al bajar a los 11 distritos y 103 municipios, casi todos empatan en la misma franja
El Centro (4,50 ★), Málaga Este (4,47 ★), Ctra. Cádiz (4,44 ★) o Teatinos (4,43 ★) parecen iguales
Si todos los barrios salen en verde, no sabes dónde hay ruido, dónde faltan aparcamientos o dónde todo va bien
Nos da apuro bajarle la nota a un camarero amable y dejamos 4 o 5 estrellas
Antes del «pero» se aplaude el trato; detrás aparece la incomodidad real
El calor por falta de sombra o la saturación del local quedan ocultos en el texto
«El espeto estaba muy bueno y el camarero fue un encanto...»
«... en la terraza hacía mucho calor porque no había sombrillas y el interior estaba un poco abarrotado.»
Separar el halago cortés de la queja real (aparcamiento, colas, precios o ruido) en 4,87 M de reseñas
Medir el peso de la costa y del Centro frente al interior, y comparar al visitante extranjero con el vecino local
Localizar zonas cercanas con identidad sin agobios y descubrir grandes locales fuera de las rutas saturadas
Seguir la evolución 2019–2026 en cada sector afectado sin que la media provincial esconda qué mejora y qué se deteriora
Nos dice que hubo ruido, colas o calor, pero no qué ocurría alrededor en esa calle
No es igual una queja a 24 °C que con terral a 38 °C, ni en zona de hoteles que de pisos turísticos
Cruzamos el entorno del local con el clima de la temporada, los flujos de paso y la franja citada en el texto
Opiniones en 10.402 POIs activos en Google Maps y 45.733 establecimientos unificados (8.706 POIs públicos y 37.027 alojamientos).
Censo oficial de pisos turísticos (agregados por celda H3) frente a hoteles reglados en cada barrio.
Episodios de terral por ventana temporal para distinguir calor climático de falta de sombra.
Flujos de paso agregados entre la Costa del Sol, el interior y los distritos de la capital.
return 0).# 1. Calcula SHA-256 y compara contra SQLite (sync_manifest.db)
df_sha256 = compute_dataframe_sha256(df)
existing_sha = get_local_content_hash(self.SOURCE_NAME, table_name)
if hashes_match(existing_sha, df_sha256):
return 0 # Sin cambios: omite escritura Parquet
# 2. Si cambió, persiste en bronze/<source>/<table>.parquet
return write_local_bronze_parquet(
df, source=self.SOURCE_NAME, table_name=table_name,
content_sha256=df_sha256,
)Recibimos el JSON, CSV o Excel en memoria con sus columnas intactas.
Calculamos el hash sobre los datos reales y lo cruzamos con sync_manifest.db.
return 0)No escribe en disco ni dispara el pipeline aguas abajo.
Guarda el lote en bruto en bronze/<fuente>.parquet.
Pasamos todas las notas a escala 1–5 ★ (Booking va de 0 a 10), unimos sus textos y eliminamos duplicados
Puntuamos completitud (ID, nota, texto, fecha, municipio INE) y desviamos lotes corruptos a quarantine/
Convertimos el autor en anon:sha256 (name = NULL) y limpiamos [EMAIL], [PHONE] y [URL]
Son polígonos enormes y desiguales cuyas fronteras parten calles por la mitad y diluyen el problema en la media
Elegimos el nivel 9 (170 m de lado) porque equivale a dos manzanas a pie (~0,1 km²)
Cada celda está rodeada por 6 zonas vecinas a igual distancia, permitiendo medir cómo el ruido o el gentío se extienden a las calles de al lado
6,3 m conviven Only YOU Hotel y su Restaurante Sonora Sky & Bites, detecta distinto segmento y los mantiene como 2 POIs separados.ST_Contains) con más reseñas verificadas.
Consolida las 4 plataformas en un solo poi_id y celda h3_r9.
Asigna distrito a chiringuitos en la arena, Muelle Uno y calles frontera.
Se opina semanas después del viaje; por eso anclamos por mes de estancia (stay_date)
Unificamos "ago 2025" o "2025-3T" en claves enteras period_key (202508 y '2025-Q3')
Unimos el mes (Reseñas, AEMET, MITMA) con censos trimestrales (11.158 VUT) y el año previo
code: SOST_DENS_001 # Densidad hotelera: plazas de hotel / km²
business_meaning: # 1. Significado de negocio y qué NO incluye
phenomenon: 'concentración espacial de plazas hoteleras por km²'
interpretation: 'valores altos indican mayor presión sobre servicios'
limitations: ['solo hoteles (no incluye pisos turísticos VUT ni camping)']
aggregation: # 2. Regla matemática de agregación
is_additive: false
weight_metric: TERR_SUP_001 # Ponderar siempre por superficie (km²)
invalid_aggregations: [sum, avg_unweighted]
ai_context: # 3. Contexto para la IA y errores habituales
common_misuses: ['sumar densidades entre zonas', 'comparar sin km²']
lineage: # Fuente oficial del dato
survey: 'INE Encuesta de Ocupación Hotelera (EOH) + Superficie INE'
# ... (+310 líneas en el YAML v2.5: quality, statistical_disclosure, bq_integration, analytics_profile... clic para ver entero)
Documenta qué fenómeno mide, cómo se interpreta y qué deja fuera (ej. solo plazas de hotel INE, sin VUT ni campings)
Declara si se puede sumar o no (is_additive: false), su variable de ponderación (km²) y el umbral de secreto estadístico
Registra qué errores de lectura existen sobre esa métrica (common_misuses), su fuente oficial y su tabla en BigQuery
class SinglePassAspectExtraction(BaseModel):
# 1. Los 6 ejes operativos (-1.0 muy negativo a +1.0 muy positivo, o None si no se menciona)
service: float | None = Field(None, ge=-1, le=1, description="Trato, camareros y calidad de la comida")
noise: float | None = Field(None, ge=-1, le=1, description="Ruido nocturno, música o jaleo en la calle")
cleanliness: float | None = Field(None, ge=-1, le=1, description="Limpieza del local o basura en la calle")
pricing: float | None = Field(None, ge=-1, le=1, description="Relación calidad-precio, cuenta o cobros")
queues: float | None = Field(None, ge=-1, le=1, description="Colas, esperas de mesa o aparcamiento")
weather_heat: float | None = Field(None, ge=-1, le=1, description="Calor extremo al sol, terraza o lluvia")
# 2. Giro del «PERO», franja horaria vivida en el texto y alerta de ironía / sarcasmo
has_adversative_pivot: bool = Field(False, description="True si contrapone ideas con 'pero' o 'aunque'")
sentiment_before_but: float | None = Field(None, ge=-1, le=1, description="Sentimiento antes del 'pero'")
sentiment_after_but: float | None = Field(None, ge=-1, le=1, description="Sentimiento real tras el 'pero'")
lived_time_slot: TimeSlot = Field("no_especificado", description="Franja inferida ('14:30h', '2 AM')")
suspected_irony: bool = Field(False, description="True si hay sarcasmo o choque estrellas vs texto")
Vectorizamos con bge-m3 reseñas en alemán, inglés, francés, neerlandés o español en el mismo espacio
Si estrellas y texto coinciden o tratan 1–2 temas claros, Qwen rellena en local el contrato Pydantic
Cuando chocan las estrellas con las palabras o un «PERO» mezcla ≥ 3 temas, salta la alarma a la nube
5 ★ «Espeto increíble y servicio rápido a las 14h») → se puntúan los 6 ejes y la hora en local.1 ★ con palabras de elogio («¡Qué maravilla 1h de cola al sol!») o 5 ★ con léxico de ruido/abuso.
00:00–06:00.
Separa el elogio antes del «PERO» (+0,95 al trato y al pescaíto) de las 3 quejas posteriores en la misma frase
Puntúa cada eje mencionado (-1 a +1), deja el resto en null e infiere la hora («a partir de las 12 de la noche»)
Enviamos las ~390.000 reseñas complejas en lotes con el prompt cacheado y el mismo contrato Pydantic
service a -0.20 a pesar del elogio inicial) o pierde la última queja del pan.| Dimensión / Paso aplicado | A lo bruto (100 % Nube individual) | Con los 3 pasos (Motor híbrido) | Impacto |
|---|---|---|---|
| Paso 1 · Pasadas por reseña | 5 llamadas separadas por reseña | 1 sola pasada JSON (contrato Pydantic) | 5x menos llamadas |
| Paso 2 · Reseñas directas (92 % · 4,48 M) | API en la nube (pago por token) | GPU local con Ollama (bge-m3 + Qwen · 0 €) | 0 € en el 92 % |
| Paso 3 · Envío del 8 % complejo (~390k) | Peticiones sueltas sin caché | Batch API (-50 %) + Context Caching (-75 %) | -75 % en prompt |
| Tiempo total de ejecución | 38 horas | 2,4 horas | -93,7 % tiempo |
| Coste total (en Gemini 3.8 Flash) | 1.450 € / ejecución | < 14 € / ejecución | -99,0 % coste |
Centro (4,50 ★), Málaga Este (4,47 ★) y Teatinos (4,43 ★) parecen idénticos si solo miras su nota global
Fuera del anillo ámbar están las fortalezas (+0,88 en trato); dentro del anillo, las fricciones reales (-0,64 en ruido)
Actuar en convivencia nocturna en el Centro, movilidad al mediodía en el Este y proteger las joyas de barrio
H3 y pueblos pequeños (con 3 amigos suben a 5,0 ★ o con 2 quejas caen a 3,50 ★).n) con un colchón comarcal (m = 50) tanto en estrellas (1–5 ★) como en los 6 ejes.En un pueblo con 12 reseñas, dos malas notas por lluvia hunden su media bruta a 3,50 ★
Sumamos un colchón de 50 reseñas con la media de su comarca (4,45 ★) que estabiliza la nota en 4,26 ★
Con > 50.000 reseñas manda el dato local (99,9 %); en pueblos o celdas H3 evita falsas alarmas
Unimos por hexágono H3 y periodo los 6 ejes extraídos del texto (filas) con los datos oficiales del territorio (columnas) y calculamos CORR(queja, dato).
El rojo (≥ 0,70) revela con qué factor de la calle sube cada queja. En cambio, al ver «Trato y comida» siempre en gris (< 0,15), deducimos que no depende del barrio sino del propio local.
Al separar el alojamiento reglado en dos columnas, vemos que el ruido nocturno se dispara con los pisos VUT (+0,82, rojo) pero no con los hoteles (+0,14, gris).
CORR(queja_h3, dato_h3)
Cruce por celda H3 (170 m) · FDR q < 0,05
SELECT CORR(a.value, b.value) AS pearson_r FROM panel a JOIN panel b USING (region_id, period_key)
0,00 = independiente · +1,00 = suben juntos
-1..+1) + «PERO»H3 r9 + VUTanon:sha256 ↓Al analizar los temas del texto, la gente aplaude el trato amable (+0,76) y la comida (+0,71)
Esas mismas reseñas de 4 y 5 ★ se quejan de aparcar (-0,52), de las colas (-0,48) y de los precios (-0,41)
En los bares más famosos del Centro (1 de cada 4 reseñas con queja de colas) y en Nerja, Frigiliana o Ronda
3 comarcas de costa suman el 87,7 %; el interior lidera en ★.
Misma nota ★, pero el extranjero sufre +24,5 % de colas.
Nota del vecino frente al turista por sector.
Al restar las quejas de saturación a los elogios de autenticidad, Puerto de la Torre (+4,75 pp) y Bailén-Miraflores (+4,64 pp) lideran frente al Centro (-2,69 pp)
Entre los 1.538 locales consolidados de cara al público (sin alojamientos), afloran 135 sitios con 15,2 % de autenticidad y sin colas ocultos tras los rankings
Negocios tradicionales consolidados donde come el vecino sin sobreprecio (15,9 % autenticidad), frente a 47 locales en trampa turística (3,51 ★) y 115 en declive
Cualquier usuario o agente pregunta en español sin escribir SQL libre ni inventar fórmulas o decimales
Solo invoca funciones tipadas (get_metric_definition y get_metric_value) con guardrails e InfoHint ⓘ
Las cifras de estas 34 diapositivas se han consultado y verificado contra los 18 Parquets Gold usando este MCP
ⓘ): % de reseñas con texto que citan colas o masificación. Equilibrio local: < 0,20 %.
D01 Centro: 0,89 % (1,05 M res.)D04 Bailén: 0,14 % (6.865 res.)
0,89 %) que Bailén-Miraflores (0,14 %). Según la definición oficial de REP_SAT_001, Bailén está en equilibrio local (< 0,20 %), mientras el Centro supera el umbral crítico por colas en hora punta.»
MCP.
18/18 Parquets ✓
Señalan la zona en rojo con quejas de colas y aparcamiento (D01 Centro, -0,55) y los POIs de Joyas Ocultas (★ 4,8 sin esperas)
Las flechas azules (➤) muestran que el 36 % de esa saturación viene de desplazamientos desde la costa en horas punta
La isócrona verde (≤ 15 min reales) muestra qué Joyas Ocultas recomendar para comer o visitar sin sufrir la saturación
D01) y Joyas (★ 4,8).Comparar Ronda con Marbella no sirve: buscamos en España otro casco histórico encajonado que viva exactamente la misma presión
Normaliza las fuentes de la charla: reseñas (★ y «PERO»), movilidad MITMA, planta hotelera/VUT y clima AEMET
Permite compartir diagnóstico entre ciudades hermanas y comprobar qué medidas reducen de verdad las quejas frente a su gemelo
RONDA · 4,53 ★ (202.360 res.)
ALBARRACÍN · GEMELO AL 95 %
La Etapa 05 fotografiaba dónde duele hoy; la Etapa 07 sigue la evolución (2019–2026) por sector para que la media provincial no diluya las alertas
Al abrirse locales en nuevas zonas (246 → 377), sube la nota media (4,38 → 4,62 ★) y se reparte mejor la espera por establecimiento
Entre los 1.538 locales consolidados afloran 115 clásicos en declive (≤ -0,25 ★ en 24m y 19,4 % disonancia), +127 % en sobreprecio (47 en trampa a 3,51 ★) y ×6 en ruido del Centro (61/100)
Prometer un decimal exacto en una calle viva engaña y oculta el riesgo.
Predice suelo y techo (LightGBM) y calibra la anchura con errores reales pasados.
En 9 de cada 10 casos acierta la banda: sabes que como mínimo reduces un -4 %.
-4 %.q₀.₀₅) y techo (q₀.₉₅) en vez de la media.Se inauguran muchos planes, pero casi nunca se audita medio año después si funcionaron
Si cambia el clima o la temporada, una bajada bruta no demuestra que fuera mérito tuyo
Confrontamos automáticamente la banda que predijo CQR con el impacto real en la calle
k-ring ≥ 3).# Etapa 07 Aprendizaje: Y_it = α + γ·D_i + λ·T_t + τ_DiD·(D_i × T_t) + ε_it
did_result = realityops.evaluate_intervention(
treated_h3=centro_d01_high_vut_cells,
control_h3=gower_matched_controls_k_ring_gt_3,
pre_window='2025-Q1..Q2', post_window='2025-Q3..Q4'
)
# Estrellas: +0,24★ (4,38→4,62★) | Rebote: 8x brunch, +127% precio, 6x ruidoDescontamos la tendencia general de Málaga para medir solo el impacto real ($\tau_{DiD}$)
Comparamos los hexágonos intervenidos frente a sus gemelos de control sin intervención
Verificamos matemáticamente que ambos grupos evolucionaban igual antes del cambio
Cuando cambian los equipos, suele perderse qué se probó y qué resultado dio
Sellamos cada extracción, modelo dbt, simulación CQR y auditoría DiD
Los errores corregidos recalibran los pesos para la siguiente vuelta por las 7 etapas
Turno de preguntas · Turismo, territorio, Google Cloud e IA en Málaga