20  Computación de cubos de datos OLAP

Un enfoque técnico y reproducible

Author

Diego Villalba

Published

May 19, 2026

Los cubos de datos son una forma de organizar información multidimensional para análisis resumido, exploración interactiva y toma de decisiones. En una arquitectura típica de data warehouse, los datos se extraen de sistemas transaccionales, pasan por procesos de limpieza e integración, se almacenan en un repositorio analítico y se presentan mediante reportes, minería de datos o cubos OLAP. Esta secuencia aparece en la presentación base, donde se recuerda el flujo general desde fuentes de datos hasta almacenamiento, data marts y presentación analítica (Santizo Galicia 2026).

El objetivo de este capítulo es convertir esa idea en una formulación técnica y reproducible. Se presentará el concepto de procesamiento analítico en línea, la estructura matemática de un cubo de datos, sus principales operaciones y una implementación práctica en Python. La discusión se apoya en la tradición de almacenes de datos (Inmon 2005; Kimball and Ross 2013), en la literatura clásica sobre OLAP y cubos de datos (Chaudhuri and Dayal 1997; Gray et al. 1996), y en herramientas modernas de análisis tabular como pandas (McKinney 2010; The pandas development team 2024).

Un cubo OLAP no debe entenderse únicamente como una figura tridimensional. En realidad, es una abstracción para representar medidas agregadas sobre varias dimensiones. Por ejemplo, una empresa puede analizar ventas por tiempo, región y producto. Cada combinación específica de esas dimensiones define una celda del cubo, y esa celda contiene una medida, como ventas totales, unidades vendidas, costo promedio o margen de ganancia.

20.1 Del almacén de datos al análisis OLAP

Un sistema transaccional u OLTP (Online Transaction Processing) está optimizado para registrar operaciones individuales: compras, pagos, inventarios, altas de clientes o movimientos bancarios. En contraste, un sistema OLAP (Online Analytical Processing) está optimizado para consultar datos agregados y responder preguntas de negocio. Esta distinción es importante porque el análisis multidimensional requiere estructuras distintas a las de una base de datos operacional.

Note

Definición. Un sistema OLAP es una estructura analítica que organiza medidas cuantitativas mediante dimensiones categóricas o jerárquicas para permitir consultas agregadas desde distintas perspectivas. \[ C : D_1 \times D_2 \times \cdots \times D_k \longrightarrow \mathbb{R}^m \]

En esta definición, \(D_1,\ldots,D_k\) representan dimensiones como tiempo, región, producto o sucursal. El valor \(C(d_1,\ldots,d_k)\) contiene una o varias medidas agregadas. Por ejemplo, si \(D_1\) es tiempo, \(D_2\) es región y \(D_3\) es producto, entonces una celda puede representar las ventas de computadoras en la región Centro durante el trimestre T1.

La presentación original destaca que en un data warehouse los datos se organizan en una estructura multidimensional, que puede implementarse como un cubo OLAP y analizarse desde diferentes perspectivas (Santizo Galicia 2026). Esta idea se puede conectar con tres componentes esenciales:

  1. Dimensiones: ejes de análisis, como tiempo, región o producto.
  2. Jerarquías: niveles dentro de una dimensión, como día \(\rightarrow\) mes \(\rightarrow\) trimestre \(\rightarrow\) año.
  3. Medidas: variables numéricas agregables, como ventas, unidades, utilidad o presupuesto.

Una ventaja central de OLAP es que permite adaptar el nivel de detalle a cada usuario. Un gerente general puede consultar ventas totales por país; una dirección regional puede revisar ventas por estado; y un supervisor puede analizar ventas por tienda. La misma base de datos analítica soporta múltiples perspectivas mediante operaciones de navegación sobre el cubo.

Cubo OLAP — visualizador interactivo
Dimensiones: Región × Tiempo × Producto  ·  Medida: Ventas (100K MXN)
Ventas bajas altas celda fuera del subcubo

20.2 Modelo multidimensional

Supongamos un conjunto de transacciones \(\mathcal{T}\) donde cada registro contiene atributos de dimensión y una medida de ventas. Una transacción puede escribirse como

\[ t_i = (r_i, \tau_i, p_i, v_i), \]

donde \(r_i\) indica la región, \(\tau_i\) el periodo, \(p_i\) el producto y \(v_i\) el valor de venta. El cubo agregado por suma se obtiene agrupando transacciones que comparten las mismas coordenadas dimensionales.

Note

Definición. Dado un conjunto de transacciones \(\mathcal{T}\), el valor de una celda de un cubo de ventas se define como la suma de las ventas de todas las transacciones que coinciden con una combinación de dimensiones: \[ C(r,\tau,p)=\sum_{i:\; r_i=r,\; \tau_i=\tau,\; p_i=p} v_i \]

Esta formulación deja claro que un cubo es una función agregada. La representación visual tridimensional es útil para enseñar el concepto, pero en la práctica pueden existir muchas más dimensiones. Un cubo de ventas real puede incluir canal de venta, tipo de cliente, vendedor, tienda, campaña publicitaria y categoría fiscal.

20.2.1 Dimensiones, medidas y granularidad

La granularidad indica el nivel de detalle con que se almacenan o consultan los datos. Una tabla con ventas diarias por tienda y producto tiene mayor granularidad que una tabla con ventas mensuales por región y categoría. Diseñar correctamente la granularidad es una decisión crítica en un almacén de datos, porque afecta el almacenamiento, la velocidad de consulta y la flexibilidad analítica (Kimball and Ross 2013).

Note

Definición. La granularidad de un cubo es el nivel mínimo de detalle con el que se representan sus dimensiones. \[ G(C)=\{\ell_1,\ell_2,\ldots,\ell_k\} \]

Aquí \(\ell_j\) representa el nivel usado en la dimensión \(D_j\). Por ejemplo, \(G(C)=\{\text{mes},\text{estado},\text{producto}\}\) indica que el cubo se consulta por mes, estado y producto. Si se cambia de mes a semana, la granularidad aumenta; si se cambia de estado a país, la granularidad disminuye.

20.3 Operaciones fundamentales en cubos OLAP

Las operaciones OLAP permiten navegar entre distintos niveles y subconjuntos del cubo. La presentación base introduce cinco operaciones principales: drill-down, roll-up, slice, dice y pivot o rotate (Santizo Galicia 2026). A continuación se formalizan y se muestran ejemplos reproducibles.

20.3.1 Drill-down

El drill-down permite pasar de datos resumidos a datos más detallados. Por ejemplo, si una empresa observa que en 2025 vendió 1,000 productos, puede preguntar cuánto se vendió por trimestre, por mes, por estado o por producto. En términos de jerarquías, el drill-down se mueve hacia niveles más específicos.

Note

Definición. Una operación de drill-down reemplaza un nivel agregado \(\ell\) de una dimensión por un nivel más detallado \(\ell'\) dentro de la misma jerarquía. \[ \ell' \prec \ell \]

Por ejemplo, en la jerarquía temporal

\[ \text{año} \rightarrow \text{trimestre} \rightarrow \text{mes} \rightarrow \text{semana} \rightarrow \text{día}, \]

pasar de año a trimestre o de mes a semana es una operación de drill-down. En la presentación, esta operación se ilustra al pasar de una vista mensual a una vista semanal para el mes de enero (Santizo Galicia 2026).

20.3.2 Roll-up

El roll-up es la operación inversa. Permite agrupar datos detallados para obtener resúmenes de mayor nivel. Por ejemplo, las ventas diarias pueden agregarse como ventas mensuales, trimestrales o anuales; las ventas por tienda pueden agregarse como ventas por estado o por país.

Note

Definición. Una operación de roll-up reemplaza un nivel detallado \(\ell'\) de una dimensión por un nivel más agregado \(\ell\) y combina las celdas mediante una función de agregación \(A\). \[ C_{\ell}(d)=A\left(\{C_{\ell'}(d'):\; d' \mapsto d\}\right) \]

La función \(A\) puede ser una suma, un promedio, un máximo, un conteo o una medida derivada. En ventas suele usarse la suma; en precios puede ser más adecuado usar promedio ponderado; en inventarios puede usarse el valor final de periodo.

20.3.3 Slice

La operación slice fija un valor específico en una dimensión y devuelve un subcubo con una dimensión menos. Si el cubo original tiene dimensiones Región, Tiempo y Producto, fijar Producto = Tablets produce una vista Región \(\times\) Tiempo.

Note

Definición. Dado un cubo \(C:D_1\times\cdots\times D_k\rightarrow\mathbb{R}\), una operación slice fija una dimensión \(D_j\) en un valor \(a\in D_j\). \[ C_{D_j=a}(d_1,\ldots,d_{j-1},d_{j+1},\ldots,d_k)=C(d_1,\ldots,a,\ldots,d_k) \]

La presentación ejemplifica esta operación al seleccionar un solo estado, un solo producto o un solo mes (Santizo Galicia 2026).

20.3.4 Dice

La operación dice selecciona subconjuntos en dos o más dimensiones al mismo tiempo. A diferencia de slice, que fija un único valor en una dimensión, dice puede conservar varios valores por dimensión.

Note

Definición. Una operación dice restringe el cubo a subconjuntos \(S_j\subseteq D_j\) en una o varias dimensiones. \[ C_{S_1,\ldots,S_k}=C\big|_{S_1\times\cdots\times S_k} \]

Por ejemplo, se puede seleccionar Tiempo \(\in \{\text{Enero},\text{Febrero}\}\) y Producto \(\in \{\text{Smartphones},\text{Tablets}\}\). También se puede restringir Región \(\in \{\text{Jalisco},\text{Estado de México}\}\) y Tiempo \(\in \{\text{Enero},\text{Febrero}\}\).

20.3.5 Pivot o rotate

La operación pivot cambia la orientación de la vista sin alterar los datos subyacentes. En una tabla, esto equivale a intercambiar filas y columnas o a reordenar dimensiones para responder otra pregunta. Por ejemplo, una tabla con semanas en filas y productos en columnas responde: “¿cuánto se vendió de cada producto en cada semana?”. Al pivotar, una tabla con productos en filas y semanas en columnas responde: “¿cómo se comportó cada producto a lo largo de las semanas?” (Santizo Galicia 2026).

Note

Definición. Una operación pivot aplica una permutación \(\pi\) al orden de las dimensiones de un cubo. \[ C^{\pi}(d_{\pi(1)},\ldots,d_{\pi(k)})=C(d_1,\ldots,d_k) \]

Esta operación es especialmente útil para visualización. No cambia la granularidad ni los valores agregados; cambia la forma en que se presentan los ejes.

20.4 Cálculo manual de un cubo OLAP en un dataset pequeño

Antes de implementar operaciones OLAP con Python, conviene resolver un ejemplo pequeño a mano. El objetivo didáctico es que el estudiante pueda reconocer las dimensiones, identificar las celdas del cubo, calcular totales y ejecutar operaciones básicas como slice y roll-up sin depender todavía de una biblioteca computacional.

Consideremos una empresa con ventas trimestrales por tiempo, ubicación y departamento. Los departamentos son

\[ (M,P,D,E)=(\text{Madera},\text{Plomería},\text{Decoración},\text{Eléctrico}). \]

La medida del cubo será el valor de ventas. Las dimensiones son:

  • \(D_1=\text{Ubicación}=\{\text{CDMX},\text{Guadalajara},\text{Monterrey},\text{Mérida}\}\).
  • \(D_2=\text{Tiempo}=\{T1,T2\}\).
  • \(D_3=\text{Departamento}=\{M,P,D,E\}\).

Por tanto, el cubo puede representarse como una función

\[ C:\text{Ubicación}\times \text{Tiempo}\times \text{Departamento}\longrightarrow \mathbb{R}. \]

La siguiente tabla contiene los datos originales.

Tiempo CDMX \((M,P,D,E)\) Guadalajara \((M,P,D,E)\)
T1 \((70,40,20,30)\) \((60,35,25,40)\)
T2 \((50,60,22,28)\) \((45,50,30,35)\)
Tiempo Monterrey \((M,P,D,E)\) Mérida \((M,P,D,E)\)
T1 \((48,38,18,26)\) \((52,42,15,37)\)
T2 \((36,55,25,30)\) \((44,33,20,28)\)

20.4.1 Paso 1: representar las celdas del cubo

Cada número de la tabla corresponde a una celda del cubo. Por ejemplo,

\[ C(\text{CDMX},T1,\text{Madera})=70, \]

\[ C(\text{CDMX},T1,\text{Eléctrico})=30, \]

\[ C(\text{Mérida},T2,\text{Plomería})=33. \]

En este caso hay

\[ 4\;\text{ubicaciones}\times 2\;\text{trimestres}\times 4\;\text{departamentos}=32 \]

celdas elementales. La representación del cubo consiste en organizar esas 32 celdas de forma que puedan consultarse por cualquiera de sus dimensiones.

20.4.2 Paso 2: calcular totales por ubicación

El total por ubicación se obtiene sumando todos los trimestres y todos los departamentos de una misma ubicación:

\[ \text{Total}(u)=\sum_{t\in\{T1,T2\}}\sum_{d\in\{M,P,D,E\}} C(u,t,d). \]

Para CDMX:

\[ \begin{aligned} \text{Total}(\text{CDMX}) &=(70+40+20+30)+(50+60+22+28)\\ &=160+160\\ &=320. \end{aligned} \]

Para Guadalajara:

\[ \begin{aligned} \text{Total}(\text{Guadalajara}) &=(60+35+25+40)+(45+50+30+35)\\ &=160+160\\ &=320. \end{aligned} \]

Para Monterrey:

\[ \begin{aligned} \text{Total}(\text{Monterrey}) &=(48+38+18+26)+(36+55+25+30)\\ &=130+146\\ &=276. \end{aligned} \]

Para Mérida:

\[ \begin{aligned} \text{Total}(\text{Mérida}) &=(52+42+15+37)+(44+33+20+28)\\ &=146+125\\ &=271. \end{aligned} \]

La tabla de totales por ubicación queda:

Ubicación Total
CDMX 320
Guadalajara 320
Monterrey 276
Mérida 271
Total general 1187

20.4.3 Paso 3: calcular totales por tiempo

El total por tiempo se obtiene sumando todas las ubicaciones y departamentos para cada trimestre:

\[ \text{Total}(t)=\sum_u\sum_d C(u,t,d). \]

Para \(T1\):

\[ \begin{aligned} \text{Total}(T1)&=(160)+(160)+(130)+(146)\\ &=596. \end{aligned} \]

Para \(T2\):

\[ \begin{aligned} \text{Total}(T2)&=(160)+(160)+(146)+(125)\\ &=591. \end{aligned} \]

Tiempo Total
T1 596
T2 591
Total general 1187

20.4.4 Paso 4: calcular totales por departamento

Ahora se suman todas las ubicaciones y tiempos para cada departamento:

\[ \text{Total}(d)=\sum_u\sum_t C(u,t,d). \]

Para Madera:

\[ 70+50+60+45+48+36+52+44=405. \]

Para Plomería:

\[ 40+60+35+50+38+55+42+33=353. \]

Para Decoración:

\[ 20+22+25+30+18+25+15+20=175. \]

Para Eléctrico:

\[ 30+28+40+35+26+30+37+28=254. \]

Departamento Total
Madera 405
Plomería 353
Decoración 175
Eléctrico 254
Total general 1187

20.4.5 Paso 5: operación slice a mano

Supongamos que se pide aplicar un slice con las siguientes condiciones:

\[ \text{ubicación}\in\{\text{CDMX},\text{Mérida}\},\qquad \text{tiempo}=T1, \]

\[ \text{departamento}\in\{\text{Madera},\text{Eléctrico}\}. \]

Aunque en sentido estricto un slice fija una dimensión en un valor, en ejercicios introductorios suele combinarse con una selección de subconjuntos. En una terminología más precisa, fijar \(T1\) es un slice, mientras que seleccionar varias ubicaciones y varios departamentos es una restricción tipo dice sobre el subcubo resultante.

Se buscan únicamente las celdas:

\[ C(\text{CDMX},T1,\text{Madera})=70, \]

\[ C(\text{CDMX},T1,\text{Eléctrico})=30, \]

\[ C(\text{Mérida},T1,\text{Madera})=52, \]

\[ C(\text{Mérida},T1,\text{Eléctrico})=37. \]

Por tanto, el resultado del subcubo es:

Ubicación Tiempo Madera Eléctrico Total
CDMX T1 70 30 100
Mérida T1 52 37 89
Total 122 67 189

20.4.6 Paso 6: operación roll-up a mano

Ahora agrupemos las ubicaciones en regiones. Una posible correspondencia es:

Ubicación Región
Monterrey Norte
CDMX Centro
Guadalajara Occidente
Mérida Sureste

El roll-up por región se calcula reemplazando la dimensión ubicación por una dimensión más agregada llamada región:

\[ C_{\text{región}}(r,t,d)=\sum_{u:\;g(u)=r} C(u,t,d), \]

donde \(g(u)\) asigna cada ubicación a su región. In this example, each region has only one location, so the numerical values are the same as the original values, but the conceptual operation is important: the cube changes from the level ubicación to the level región.

Región Tiempo Madera Plomería Decoración Eléctrico Total
Centro T1 70 40 20 30 160
Centro T2 50 60 22 28 160
Norte T1 48 38 18 26 130
Norte T2 36 55 25 30 146
Occidente T1 60 35 25 40 160
Occidente T2 45 50 30 35 160
Sureste T1 52 42 15 37 146
Sureste T2 44 33 20 28 125
Total 405 353 175 254 1187

Si se desea un roll-up regional más agregado, también se pueden definir zonas. Por ejemplo,

\[ \text{Zona Norte-Centro}=\{\text{Monterrey},\text{CDMX}\}, \]

\[ \text{Zona Occidente-Sureste}=\{\text{Guadalajara},\text{Mérida}\}. \]

Entonces, para la Zona Norte-Centro en \(T1\):

\[ \begin{aligned} C(\text{Zona Norte-Centro},T1,M)&=48+70=118,\\ C(\text{Zona Norte-Centro},T1,P)&=38+40=78,\\ C(\text{Zona Norte-Centro},T1,D)&=18+20=38,\\ C(\text{Zona Norte-Centro},T1,E)&=26+30=56. \end{aligned} \]

El resultado completo por zonas es:

Zona Tiempo Madera Plomería Decoración Eléctrico Total
Norte-Centro T1 118 78 38 56 290
Norte-Centro T2 86 115 47 58 306
Occidente-Sureste T1 112 77 40 77 306
Occidente-Sureste T2 89 83 50 63 285
Total 405 353 175 254 1187

Este ejemplo muestra que calcular un cubo a mano consiste en tres acciones básicas: identificar coordenadas dimensionales, sumar celdas según la agregación solicitada y conservar claramente el nivel de granularidad usado en cada resultado.

20.5 Ejemplo reproducible en Python

La presentación propone un ejercicio con ventas trimestrales de una empresa mexicana de electrónica. Las dimensiones son Región, Tiempo y Producto, y la medida son ventas expresadas en cientos de miles de pesos mexicanos (Santizo Galicia 2026). A continuación se construye el cubo de datos en Python.

import pandas as pd

records = [
    # Norte
    ("Norte", "T1", "Televisores", 35), ("Norte", "T1", "Computadoras", 22),
    ("Norte", "T1", "Lavadoras", 10), ("Norte", "T1", "Cámaras", 14),
    ("Norte", "T2", "Televisores", 28), ("Norte", "T2", "Computadoras", 26),
    ("Norte", "T2", "Lavadoras", 13), ("Norte", "T2", "Cámaras", 17),
    ("Norte", "T3", "Televisores", 18), ("Norte", "T3", "Computadoras", 15),
    ("Norte", "T3", "Lavadoras", 8), ("Norte", "T3", "Cámaras", 12),
    ("Norte", "T4", "Televisores", 30), ("Norte", "T4", "Computadoras", 33),
    ("Norte", "T4", "Lavadoras", 16), ("Norte", "T4", "Cámaras", 15),

    # Centro
    ("Centro", "T1", "Televisores", 40), ("Centro", "T1", "Computadoras", 30),
    ("Centro", "T1", "Lavadoras", 18), ("Centro", "T1", "Cámaras", 11),
    ("Centro", "T2", "Televisores", 32), ("Centro", "T2", "Computadoras", 28),
    ("Centro", "T2", "Lavadoras", 20), ("Centro", "T2", "Cámaras", 14),
    ("Centro", "T3", "Televisores", 25), ("Centro", "T3", "Computadoras", 19),
    ("Centro", "T3", "Lavadoras", 15), ("Centro", "T3", "Cámaras", 10),
    ("Centro", "T4", "Televisores", 38), ("Centro", "T4", "Computadoras", 35),
    ("Centro", "T4", "Lavadoras", 22), ("Centro", "T4", "Cámaras", 16),

    # Occidente
    ("Occidente", "T1", "Televisores", 20), ("Occidente", "T1", "Computadoras", 27),
    ("Occidente", "T1", "Lavadoras", 9), ("Occidente", "T1", "Cámaras", 6),
    ("Occidente", "T2", "Televisores", 24), ("Occidente", "T2", "Computadoras", 31),
    ("Occidente", "T2", "Lavadoras", 11), ("Occidente", "T2", "Cámaras", 8),
    ("Occidente", "T3", "Televisores", 29), ("Occidente", "T3", "Computadoras", 36),
    ("Occidente", "T3", "Lavadoras", 7), ("Occidente", "T3", "Cámaras", 9),
    ("Occidente", "T4", "Televisores", 19), ("Occidente", "T4", "Computadoras", 34),
    ("Occidente", "T4", "Lavadoras", 10), ("Occidente", "T4", "Cámaras", 5),

    # Sureste
    ("Sureste", "T1", "Televisores", 26), ("Sureste", "T1", "Computadoras", 17),
    ("Sureste", "T1", "Lavadoras", 12), ("Sureste", "T1", "Cámaras", 9),
    ("Sureste", "T2", "Televisores", 21), ("Sureste", "T2", "Computadoras", 20),
    ("Sureste", "T2", "Lavadoras", 16), ("Sureste", "T2", "Cámaras", 11),
    ("Sureste", "T3", "Televisores", 23), ("Sureste", "T3", "Computadoras", 18),
    ("Sureste", "T3", "Lavadoras", 14), ("Sureste", "T3", "Cámaras", 10),
    ("Sureste", "T4", "Televisores", 27), ("Sureste", "T4", "Computadoras", 24),
    ("Sureste", "T4", "Lavadoras", 19), ("Sureste", "T4", "Cámaras", 12),
]

df = pd.DataFrame(records, columns=["region", "tiempo", "producto", "ventas"])
df.head()
region tiempo producto ventas
0 Norte T1 Televisores 35
1 Norte T1 Computadoras 22
2 Norte T1 Lavadoras 10
3 Norte T1 Cámaras 14
4 Norte T2 Televisores 28

20.5.1 Representación como cubo

En pandas, una forma natural de representar el cubo es usar un índice múltiple. Cada celda queda identificada por una tupla (region, tiempo, producto).

cubo = df.set_index(["region", "tiempo", "producto"]).sort_index()
cubo.head(10)
ventas
region tiempo producto
Centro T1 Computadoras 30
Cámaras 11
Lavadoras 18
Televisores 40
T2 Computadoras 28
Cámaras 14
Lavadoras 20
Televisores 32
T3 Computadoras 19
Cámaras 10

También se puede construir una vista tabular con productos como columnas. Esta vista es conveniente para reportes, aunque internamente sigue representando el mismo cubo.

vista = df.pivot_table(
    index=["region", "tiempo"],
    columns="producto",
    values="ventas",
    aggfunc="sum",
    fill_value=0,
)
vista
producto Computadoras Cámaras Lavadoras Televisores
region tiempo
Centro T1 30 11 18 40
T2 28 14 20 32
T3 19 10 15 25
T4 35 16 22 38
Norte T1 22 14 10 35
T2 26 17 13 28
T3 15 12 8 18
T4 33 15 16 30
Occidente T1 27 6 9 20
T2 31 8 11 24
T3 36 9 7 29
T4 34 5 10 19
Sureste T1 17 9 12 26
T2 20 11 16 21
T3 18 10 14 23
T4 24 12 19 27

20.6 Implementación de operaciones OLAP

20.6.1 Slice: fijar un trimestre

El ejercicio pide realizar una operación slice fijando Tiempo = T2. El resultado conserva las dimensiones Región y Producto.

slice_t2 = df[df["tiempo"] == "T2"]
slice_t2.pivot_table(
    index="region",
    columns="producto",
    values="ventas",
    aggfunc="sum",
    fill_value=0,
)
producto Computadoras Cámaras Lavadoras Televisores
region
Centro 28 14 20 32
Norte 26 17 13 28
Occidente 31 8 11 24
Sureste 20 11 16 21

Esta salida permite comparar las ventas del segundo trimestre entre regiones y productos.

20.6.2 Dice: seleccionar regiones, tiempos y productos

El ejercicio también solicita una operación dice con Región = Norte o Centro, Tiempo = T1 o T4 y Producto = Televisores o Cámaras.

dice = df[
    df["region"].isin(["Norte", "Centro"])
    & df["tiempo"].isin(["T1", "T4"])
    & df["producto"].isin(["Televisores", "Cámaras"])
]

dice.pivot_table(
    index=["region", "tiempo"],
    columns="producto",
    values="ventas",
    aggfunc="sum",
    fill_value=0,
)
producto Cámaras Televisores
region tiempo
Centro T1 11 40
T4 16 38
Norte T1 14 35
T4 15 30

La operación reduce el cubo original a un subcubo con dos regiones, dos periodos y dos productos. El resultado es más pequeño, pero conserva la estructura multidimensional.

20.6.3 Roll-up: agrupar regiones en zonas

El ejercicio pide crear dos categorías regionales: Zona Norte-Centro y Zona Occidente-Sureste. Esto es un roll-up sobre la dimensión Región.

mapa_zonas = {
    "Norte": "Zona Norte-Centro",
    "Centro": "Zona Norte-Centro",
    "Occidente": "Zona Occidente-Sureste",
    "Sureste": "Zona Occidente-Sureste",
}

df_zonas = df.assign(zona=df["region"].map(mapa_zonas))

rollup_zonas = df_zonas.pivot_table(
    index=["zona", "tiempo"],
    columns="producto",
    values="ventas",
    aggfunc="sum",
    fill_value=0,
)

rollup_zonas
producto Computadoras Cámaras Lavadoras Televisores
zona tiempo
Zona Norte-Centro T1 52 25 28 75
T2 54 31 33 60
T3 34 22 23 43
T4 68 31 38 68
Zona Occidente-Sureste T1 44 15 21 46
T2 51 19 27 45
T3 54 19 21 52
T4 58 17 29 46

En este caso la función de agregación es la suma. Por ejemplo, las ventas de Televisores en T1 para Zona Norte-Centro se obtienen como Norte-T1-Televisores más Centro-T1-Televisores.

20.6.4 Pivot: cambiar la orientación de la consulta

Para estudiar la evolución temporal de cada producto, se puede pivotar la tabla y colocar productos en filas y trimestres en columnas.

pivot_producto_tiempo = df.pivot_table(
    index="producto",
    columns="tiempo",
    values="ventas",
    aggfunc="sum",
    fill_value=0,
)

pivot_producto_tiempo
tiempo T1 T2 T3 T4
producto
Computadoras 96 105 88 126
Cámaras 40 50 41 48
Lavadoras 49 60 44 67
Televisores 121 105 95 114

Esta vista responde una pregunta distinta: ya no se enfatiza la región, sino el comportamiento temporal agregado de cada producto.

20.7 Exploración interactiva del cubo

Los bloques siguientes permiten explorar las cinco operaciones OLAP directamente en el navegador. Los controles están conectados al mismo conjunto de datos construido en Python. El código OJS se ejecuta en el cliente, por lo que no requiere un servidor activo: funciona en el sitio estático de GitHub Pages.

20.7.1 Slice

Fija una dimensión en un valor único. El subcubo resultante conserva las dos dimensiones restantes y muestra su distribución de ventas.

viewof slice_dim = Inputs.radio(
  ["tiempo", "region", "producto"],
  {label: "Dimensión fija", value: "tiempo"}
)

viewof slice_val = Inputs.select(
  slice_dim === "tiempo"   ? tiempos   :
  slice_dim === "region"   ? regiones  : productos,
  {label: "Valor"}
)

20.7.2 Roll-up y Drill-down

Cambia el nivel de agregación de la dimensión geográfica. Seleccionar Zona aplica un roll-up que agrupa regiones; volver a Región aplica un drill-down que recupera el detalle.

viewof nivel_geo = Inputs.radio(
  ["Región  (drill-down)", "Zona  (roll-up)"],
  {label: "Nivel geográfico", value: "Región  (drill-down)"}
)

20.7.3 Dice

Selecciona subconjuntos en dos o más dimensiones al mismo tiempo. Desmarcar opciones reduce el subcubo; la gráfica y la tabla se actualizan en tiempo real.

viewof dice_reg  = Inputs.checkbox(regiones,  {label: "Regiones",    value: regiones})
viewof dice_tpo  = Inputs.checkbox(tiempos,   {label: "Trimestres",  value: tiempos})
viewof dice_prod = Inputs.checkbox(productos, {label: "Productos",   value: productos})

20.8 Agregaciones y medidas derivadas

Las medidas de un cubo pueden ser simples o derivadas. Una medida simple es la suma de ventas; una medida derivada puede ser participación porcentual, crecimiento trimestral o margen. En OLAP conviene distinguir entre medidas aditivas, semi-aditivas y no aditivas (Kimball and Ross 2013).

Note

Definición. Una medida aditiva puede agregarse mediante suma a lo largo de todas las dimensiones relevantes del cubo. \[ M(A\cup B)=M(A)+M(B),\qquad A\cap B=\varnothing \]

Las ventas son usualmente aditivas: se pueden sumar por producto, región y tiempo. En cambio, una tasa de conversión no debe agregarse sumando porcentajes; debe recalcularse a partir de numeradores y denominadores.

El siguiente ejemplo calcula ventas totales por producto y participación porcentual dentro del total.

ventas_producto = (
    df.groupby("producto", as_index=False)["ventas"]
    .sum()
    .assign(participacion=lambda x: x["ventas"] / x["ventas"].sum())
)

ventas_producto
producto ventas participacion
0 Computadoras 415 0.332266
1 Cámaras 179 0.143315
2 Lavadoras 220 0.176141
3 Televisores 435 0.348279

También se puede calcular el crecimiento entre trimestres para cada producto. En este caso, el cubo se reorganiza por producto y tiempo.

ventas_tiempo = (
    df.groupby(["producto", "tiempo"], as_index=False)["ventas"]
    .sum()
    .sort_values(["producto", "tiempo"])
)

ventas_tiempo["crecimiento"] = ventas_tiempo.groupby("producto")["ventas"].pct_change()
ventas_tiempo
producto tiempo ventas crecimiento
0 Computadoras T1 96 NaN
1 Computadoras T2 105 0.093750
2 Computadoras T3 88 -0.161905
3 Computadoras T4 126 0.431818
4 Cámaras T1 40 NaN
5 Cámaras T2 50 0.250000
6 Cámaras T3 41 -0.180000
7 Cámaras T4 48 0.170732
8 Lavadoras T1 49 NaN
9 Lavadoras T2 60 0.224490
10 Lavadoras T3 44 -0.266667
11 Lavadoras T4 67 0.522727
12 Televisores T1 121 NaN
13 Televisores T2 105 -0.132231
14 Televisores T3 95 -0.095238
15 Televisores T4 114 0.200000

20.9 Ventajas, limitaciones y criterios de diseño

La presentación enumera como ventajas de OLAP el análisis rápido de grandes datos, la visión multidimensional, la identificación de patrones y tendencias, el soporte para decisiones y la comparación entre periodos, regiones o productos (Santizo Galicia 2026). Estas ventajas se explican por la preagregación, el modelado dimensional y la separación entre cargas transaccionales y cargas analíticas.

Sin embargo, OLAP también tiene limitaciones. Puede requerir mucho almacenamiento, no siempre se actualiza en tiempo real, el diseño del cubo puede ser complejo y depende de una buena calidad de datos (Santizo Galicia 2026). En un entorno profesional, estas limitaciones se traducen en decisiones concretas:

  • Definir qué dimensiones realmente aportan valor analítico.
  • Elegir la granularidad mínima necesaria.
  • Evitar jerarquías ambiguas o inconsistentes.
  • Validar calidad de datos antes de construir agregados.
  • Documentar las reglas de negocio usadas en cada medida.

Un error común consiste en pensar que un cubo OLAP resuelve automáticamente la calidad de los datos. En realidad, el cubo amplifica los problemas de integración: categorías mal escritas, fechas incompletas, productos duplicados o regiones inconsistentes pueden producir agregaciones incorrectas.

20.10 Buenas prácticas para documentación reproducible

Cuando un cubo se usa en un reporte técnico o curso de ciencia de datos, conviene documentar el proceso completo: fuente de datos, transformaciones, reglas de agregación y consultas realizadas. Quarto permite combinar explicación, matemáticas, código ejecutable y resultados en un mismo documento. Para que el análisis sea reproducible, se recomienda:

  1. Cargar los datos desde una fuente controlada.
  2. Construir el cubo mediante código, no manualmente.
  3. Separar definiciones conceptuales de operaciones computacionales.
  4. Mostrar consultas representativas: slice, dice, roll-up, drill-down y pivot.
  5. Verificar que las agregaciones coincidan con las reglas de negocio.

El siguiente bloque resume una función reutilizable para construir vistas OLAP simples a partir de una tabla larga.

def vista_olap(datos, filas, columnas, medida="ventas", agregacion="sum"):
    """Construye una vista tabular tipo OLAP con pandas.

    Parameters
    ----------
    datos : pandas.DataFrame
        Tabla en formato largo.
    filas : str or list[str]
        Dimensiones colocadas en las filas.
    columnas : str or list[str]
        Dimensiones colocadas en las columnas.
    medida : str
        Variable numérica que se agregará.
    agregacion : str or callable
        Función de agregación, por ejemplo "sum", "mean" o "count".
    """
    return datos.pivot_table(
        index=filas,
        columns=columnas,
        values=medida,
        aggfunc=agregacion,
        fill_value=0,
    )

vista_olap(df, filas=["region", "tiempo"], columnas="producto")
producto Computadoras Cámaras Lavadoras Televisores
region tiempo
Centro T1 30 11 18 40
T2 28 14 20 32
T3 19 10 15 25
T4 35 16 22 38
Norte T1 22 14 10 35
T2 26 17 13 28
T3 15 12 8 18
T4 33 15 16 30
Occidente T1 27 6 9 20
T2 31 8 11 24
T3 36 9 7 29
T4 34 5 10 19
Sureste T1 17 9 12 26
T2 20 11 16 21
T3 18 10 14 23
T4 24 12 19 27

20.11 Conclusiones

Los cubos de datos OLAP son una herramienta central para organizar, resumir y explorar información multidimensional. Su valor no está solo en la representación visual de un cubo, sino en el modelo conceptual que conecta dimensiones, jerarquías, medidas y operaciones de navegación. A partir de una tabla transaccional, un cubo permite responder preguntas como: cuánto se vendió, dónde se vendió, cuándo ocurrió, qué productos dominaron y cómo cambian los patrones al modificar el nivel de agregación.

Las operaciones drill-down, roll-up, slice, dice y pivot constituyen el lenguaje básico para interactuar con un cubo. En conjunto, permiten pasar de resúmenes ejecutivos a análisis detallados, restringir subconjuntos relevantes y reorientar la información según la pregunta de negocio. Implementarlas en Python con pandas facilita la reproducibilidad y ayuda a conectar la teoría de OLAP con prácticas modernas de ciencia de datos.

Finalmente, el diseño de un cubo exige decisiones cuidadosas sobre granularidad, calidad de datos, jerarquías y medidas. Un cubo bien diseñado mejora la interpretación y la toma de decisiones; un cubo mal diseñado puede producir conclusiones engañosas aunque las consultas sean técnicamente correctas.

20.12 Referencias

Han, Jiawei, Micheline Kamber, and Jian Pei. 2011. Data Mining: Concepts and Techniques. 3rd ed. Waltham, MA: Morgan Kaufmann. https://doi.org/10.1016/B978-0-12-381479-1.00001-0.
Hastie, Trevor, Robert Tibshirani, and Jerome Friedman. 2009. The Elements of Statistical Learning: Data Mining, Inference, and Prediction. 2nd ed. Springer Series in Statistics. New York, NY: Springer. https://doi.org/10.1007/978-0-387-84858-7.
James, Gareth, Daniela Witten, Trevor Hastie, and Robert Tibshirani. 2021. An Introduction to Statistical Learning with Applications in R. 2nd ed. Springer Texts in Statistics. New York, NY: Springer. https://doi.org/10.1007/978-1-0716-1418-1.
Provost, Foster, and Tom Fawcett. 2013. Data Science for Business: What You Need to Know about Data Mining and Data-Analytic Thinking. Sebastopol, CA: O’Reilly Media.