Executive result map
Mapa ejecutivo de resultados
Every analytical block below now includes its executed numerical output—not only the code and interpretation.
Cada bloque analítico incluye ahora su salida numérica ejecutada, no solamente el código y la interpretación.
1. Data loading and schema verification
1. Carga de datos y verificación de esquemas
BASE_PATH = "/Volumes/workspace/default/contextual_mesh"
df_sales = spark.read.option("header", True).option("inferSchema", True).csv(
f"{BASE_PATH}/silver_product_sales_monthly.csv"
)
df_context = spark.read.option("header", True).option("inferSchema", True).csv(
f"{BASE_PATH}/silver_context_monthly.csv"
)
df_rules = spark.read.option("header", True).option("inferSchema", True).csv(
f"{BASE_PATH}/gold_expert_rules.csv"
)
df_ground_truth = spark.read.option("header", True).option("inferSchema", True).csv(
f"{BASE_PATH}/gold_ground_truth_validation.csv"
)
df_sources = spark.read.option("header", True).option("inferSchema", True).csv(
f"{BASE_PATH}/source_catalog.csv"
)
Executed output
Salida ejecutada
| Dataset | Rows | Columns |
|---|---|---|
| sales | 120 | 14 |
| context | 600 | 8 |
| rules | 12 | 11 |
| ground_truth | 12 | 6 |
| sources | 6 | 8 |
The five datasets loaded without row loss. Spark inferred the monthly date field correctly.
Los cinco datasets cargaron sin pérdida de filas. Spark infirió correctamente el campo mensual de fecha.
2. Evidence matrix builder
2. Constructor de la matriz de evidencia
evidence = (
df_rules.alias("r")
.join(
df_context.alias("c"),
F.col("r.ContextFactor") == F.col("c.ContextFactor"),
"inner"
)
.join(
df_sales.alias("s"),
(
(F.col("r.Product") == F.col("s.Product")) &
(F.col("r.ProductLine") == F.col("s.ProductLine")) &
(F.col("c.Month") == F.col("s.Month")) &
(F.col("c.Market") == F.col("s.Market"))
),
"inner"
)
.select(
F.col("c.Month").alias("Month"),
F.col("c.Market").alias("Market"),
F.col("r.ProductLine").alias("ProductLine"),
F.col("r.Product").alias("Product"),
F.col("r.ContextFactor").alias("ContextFactor"),
F.col("c.CurrentValue").alias("ContextValue"),
F.col("s.Units").alias("Units"),
F.col("s.Revenue").alias("Revenue"),
F.col("s.GrossProfit").alias("GrossProfit")
)
)
3. Index 01 — Pearson correlations
3. Índice 01 — Correlaciones Pearson
pearson_index = (
evidence
.groupBy("ProductLine", "Product", "ContextFactor")
.agg(
F.count("*").alias("Observations"),
F.corr("ContextValue", "Units").alias("Pearson_Units"),
F.corr("ContextValue", "Revenue").alias("Pearson_Revenue"),
F.corr("ContextValue", "GrossProfit").alias("Pearson_GrossProfit")
)
)
Full numerical output by rule
Salida numérica completa por regla
| Product | ContextFactor | Observations | Pearson_Units | Pearson_Revenue | Pearson_GrossProfit |
|---|---|---|---|---|---|
| Whole Milk | ConsumerSentiment | 60 | -0.009086 | -0.119472 | 0.215699 |
| Whole Milk | GasolinePrice | 60 | -0.015876 | 0.141160 | -0.186404 |
| Whole Milk | InflationRate | 60 | 0.127226 | 0.176539 | -0.186833 |
| Whole Milk | MiamiUnemploymentRate | 60 | 0.781745 | 0.026964 | -0.280282 |
| Whole Milk | MilkMarketPrice | 60 | -0.760345 | 0.588849 | 0.685919 |
| iPhone | ConsumerSentiment | 60 | 0.021862 | 0.047988 | 0.050136 |
| iPhone | FederalFundsRate | 60 | 0.019572 | 0.053827 | 0.061264 |
| iPhone | HolidayIndex | 60 | 0.713368 | 0.712609 | 0.700663 |
| iPhone | InflationRate | 60 | -0.110087 | -0.139424 | -0.143328 |
| iPhone | LaunchEvent | 60 | 0.750740 | 0.755783 | 0.769969 |
| iPhone | PromotionIntensity | 60 | 0.932398 | 0.938437 | 0.948367 |
| iPhone | SocialTrendIndex | 60 | 0.876862 | 0.880355 | 0.882015 |
For iPhone, PromotionIntensity (0.932398), SocialTrendIndex (0.876862), LaunchEvent (0.750740), and HolidayIndex (0.713368) were the strongest unit correlations. Whole Milk showed a strong positive raw correlation with MiamiUnemploymentRate (0.781745), despite a seeded negative direction.
Para iPhone, PromotionIntensity (0.932398), SocialTrendIndex (0.876862), LaunchEvent (0.750740) y HolidayIndex (0.713368) fueron las correlaciones más fuertes con unidades. Whole Milk mostró una correlación bruta positiva fuerte con MiamiUnemploymentRate (0.781745), pese a una dirección sembrada negativa.
4. Index 02 — Best lag from 0 to 6 months
4. Índice 02 — Mejor rezago de 0 a 6 meses
window_spec = (
Window
.partitionBy("ProductLine", "Product", "ContextFactor")
.orderBy("Month")
)
for lag in range(0, 7):
lagged_evidence = lagged_evidence.withColumn(
f"ContextValue_Lag_{lag}",
F.lag("ContextValue", lag).over(window_spec)
if lag > 0 else F.col("ContextValue")
)
# Compute one correlation per rule and lag, then choose
# the largest absolute correlation.
Best lag and ground-truth comparison
Mejor rezago y comparación con ground truth
| Product | ContextFactor | Correlation | LagMonths | DetectedDirection | SeededDirection | SeededLagMonths | DirectionMatch | LagErrorMonths |
|---|---|---|---|---|---|---|---|---|
| Whole Milk | ConsumerSentiment | 0.107597 | 6 | POSITIVE | POSITIVE | 0 | TRUE | 6 |
| Whole Milk | GasolinePrice | -0.172990 | 3 | NEGATIVE | NEGATIVE | 1 | TRUE | 2 |
| Whole Milk | InflationRate | 0.127226 | 0 | POSITIVE | NEGATIVE | 0 | FALSE | 0 |
| Whole Milk | MiamiUnemploymentRate | 0.781745 | 0 | POSITIVE | NEGATIVE | 0 | FALSE | 0 |
| Whole Milk | MilkMarketPrice | -0.802096 | 3 | NEGATIVE | NEGATIVE | 0 | TRUE | 3 |
| iPhone | ConsumerSentiment | 0.115968 | 6 | POSITIVE | POSITIVE | 0 | TRUE | 6 |
| iPhone | FederalFundsRate | -0.065587 | 6 | NEGATIVE | NEGATIVE | 3 | TRUE | 3 |
| iPhone | HolidayIndex | 0.713368 | 0 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
| iPhone | InflationRate | -0.117967 | 1 | NEGATIVE | NEGATIVE | 2 | TRUE | 1 |
| iPhone | LaunchEvent | 0.750740 | 0 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
| iPhone | PromotionIntensity | 0.932398 | 0 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
| iPhone | SocialTrendIndex | 0.876862 | 0 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
Summary
Resumen
| Metric | Value |
|---|---|
| Rules evaluated | 12.0000 |
| Correct directions | 10.0000 |
| Exact lag matches | 6.0000 |
| Lag matches within ±1 month | 7.0000 |
| Mean absolute lag error | 1.7500 |
5. Regularized lag selector
5. Selector regularizado de rezagos
regularized_lag_index = (
lag_index
.withColumn("AbsCorrelation", F.abs("Correlation"))
.withColumn(
"LagPenalty",
F.lit(1.0) - F.col("LagMonths") * F.lit(0.05)
)
.withColumn(
"RegularizedScore",
F.col("AbsCorrelation") * F.col("LagPenalty")
)
)
Numerical result for every rule
Resultado numérico para cada regla
| Product | ContextFactor | Correlation | LagMonths | LagPenalty | RegularizedScore | DetectedDirection | SeededDirection | SeededLagMonths | DirectionMatch | LagErrorMonths |
|---|---|---|---|---|---|---|---|---|---|---|
| Whole Milk | ConsumerSentiment | 0.107597 | 6 | 0.700000 | 0.075318 | POSITIVE | POSITIVE | 0 | TRUE | 6 |
| Whole Milk | GasolinePrice | -0.172990 | 3 | 0.850000 | 0.147041 | NEGATIVE | NEGATIVE | 1 | TRUE | 2 |
| Whole Milk | InflationRate | 0.127226 | 0 | 1.000000 | 0.127226 | POSITIVE | NEGATIVE | 0 | FALSE | 0 |
| Whole Milk | MiamiUnemploymentRate | 0.781745 | 0 | 1.000000 | 0.781745 | POSITIVE | NEGATIVE | 0 | FALSE | 0 |
| Whole Milk | MilkMarketPrice | -0.760345 | 0 | 1.000000 | 0.760345 | NEGATIVE | NEGATIVE | 0 | TRUE | 0 |
| iPhone | ConsumerSentiment | 0.112094 | 5 | 0.750000 | 0.084071 | POSITIVE | POSITIVE | 0 | TRUE | 5 |
| iPhone | FederalFundsRate | -0.065587 | 6 | 0.700000 | 0.045911 | NEGATIVE | NEGATIVE | 3 | TRUE | 3 |
| iPhone | HolidayIndex | 0.713368 | 0 | 1.000000 | 0.713368 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
| iPhone | InflationRate | -0.117967 | 1 | 0.950000 | 0.112069 | NEGATIVE | NEGATIVE | 2 | TRUE | 1 |
| iPhone | LaunchEvent | 0.750740 | 0 | 1.000000 | 0.750740 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
| iPhone | PromotionIntensity | 0.932398 | 0 | 1.000000 | 0.932398 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
| iPhone | SocialTrendIndex | 0.876862 | 0 | 1.000000 | 0.876862 | POSITIVE | POSITIVE | 0 | TRUE | 0 |
Before vs. after
Antes vs. después
| Metric | Baseline | Regularized | Change |
|---|---|---|---|
| Correct directions | 10.0000 | 10.0000 | 0.0000 |
| Exact lag matches | 6.0000 | 7.0000 | 1.0000 |
| Within ±1 month | 7.0000 | 8.0000 | 1.0000 |
| Lag MAE | 1.7500 | 1.4167 | -0.3333 |
The regularizer improved exact lag recovery from 6 to 7, increased ±1-month recovery from 7 to 8, and reduced lag MAE from 1.75 to 1.4167 without losing direction accuracy.
El regularizador mejoró la recuperación exacta de rezagos de 6 a 7, aumentó la recuperación dentro de ±1 mes de 7 a 8 y redujo el MAE de 1.75 a 1.4167 sin perder precisión de dirección.
6. Index 03 — Standardized OLS partial effects
6. Índice 03 — Efectos parciales OLS estandarizados
context_wide = (
df_context
.groupBy("Month", "Market")
.pivot("ContextFactor")
.agg(F.first("CurrentValue"))
)
model_base = df_sales.join(
context_wide,
on=["Month", "Market"],
how="inner"
)
X_scaled = StandardScaler().fit_transform(X)
y_scaled = StandardScaler().fit_transform(
y.to_numpy().reshape(-1, 1)
).ravel()
model = LinearRegression()
model.fit(X_scaled, y_scaled)
| Product | ContextFactor | PartialEffect | PartialDirection | SeededDirection | DirectionMatch | ModelR2 | Observations |
|---|---|---|---|---|---|---|---|
| Whole Milk | ConsumerSentiment | -0.242470 | NEGATIVE | POSITIVE | FALSE | 0.847152 | 60 |
| Whole Milk | GasolinePrice | -0.384035 | NEGATIVE | NEGATIVE | TRUE | 0.847152 | 60 |
| Whole Milk | InflationRate | -0.459812 | NEGATIVE | NEGATIVE | TRUE | 0.847152 | 60 |
| Whole Milk | MiamiUnemploymentRate | 0.853731 | POSITIVE | NEGATIVE | FALSE | 0.847152 | 60 |
| Whole Milk | MilkMarketPrice | -0.041847 | NEGATIVE | NEGATIVE | TRUE | 0.847152 | 60 |
| iPhone | ConsumerSentiment | 0.161392 | POSITIVE | POSITIVE | TRUE | 0.974994 | 60 |
| iPhone | FederalFundsRate | -0.036512 | NEGATIVE | NEGATIVE | TRUE | 0.974994 | 60 |
| iPhone | HolidayIndex | 0.527810 | POSITIVE | POSITIVE | TRUE | 0.974994 | 60 |
| iPhone | InflationRate | 0.190575 | POSITIVE | NEGATIVE | FALSE | 0.974994 | 60 |
| iPhone | LaunchEvent | 0.408987 | POSITIVE | POSITIVE | TRUE | 0.974994 | 60 |
| iPhone | PromotionIntensity | 0.063027 | POSITIVE | POSITIVE | TRUE | 0.974994 | 60 |
| iPhone | SocialTrendIndex | 0.242249 | POSITIVE | POSITIVE | TRUE | 0.974994 | 60 |
High R² did not guarantee correct signs. The failures were Whole Milk–ConsumerSentiment, Whole Milk–MiamiUnemploymentRate, and iPhone–InflationRate.
Un R² alto no garantizó signos correctos. Los fallos fueron Whole Milk–ConsumerSentiment, Whole Milk–MiamiUnemploymentRate e iPhone–InflationRate.
7. Index 04 — Elastic Net stabilized effects
7. Índice 04 — Efectos estabilizados con Elastic Net
pipeline = Pipeline([
("scaler", StandardScaler()),
(
"model",
ElasticNetCV(
l1_ratio=[0.1, 0.25, 0.5, 0.75, 0.9, 1.0],
alphas=np.logspace(-4, 1, 100),
cv=5,
max_iter=100000,
random_state=42
)
)
])
pipeline.fit(X, y)
| Product | ContextFactor | ElasticNetEffect | ElasticNetDirection | SeededDirection | DirectionMatch | SelectedAlpha | SelectedL1Ratio |
|---|---|---|---|---|---|---|---|
| Whole Milk | ConsumerSentiment | -449.895210 | NEGATIVE | POSITIVE | FALSE | 0.037649 | 0.100000 |
| Whole Milk | GasolinePrice | -2219.834728 | NEGATIVE | NEGATIVE | TRUE | 0.037649 | 0.100000 |
| Whole Milk | InflationRate | -920.928778 | NEGATIVE | NEGATIVE | TRUE | 0.037649 | 0.100000 |
| Whole Milk | MiamiUnemploymentRate | 4229.759751 | POSITIVE | NEGATIVE | FALSE | 0.037649 | 0.100000 |
| Whole Milk | MilkMarketPrice | -1328.632800 | NEGATIVE | NEGATIVE | TRUE | 0.037649 | 0.100000 |
| iPhone | ConsumerSentiment | 177.848687 | POSITIVE | POSITIVE | TRUE | 0.033516 | 0.250000 |
| iPhone | FederalFundsRate | -91.125170 | NEGATIVE | NEGATIVE | TRUE | 0.033516 | 0.250000 |
| iPhone | HolidayIndex | 851.485366 | POSITIVE | POSITIVE | TRUE | 0.033516 | 0.250000 |
| iPhone | InflationRate | 181.558056 | POSITIVE | NEGATIVE | FALSE | 0.033516 | 0.250000 |
| iPhone | LaunchEvent | 573.110802 | POSITIVE | POSITIVE | TRUE | 0.033516 | 0.250000 |
| iPhone | PromotionIntensity | 301.433372 | POSITIVE | POSITIVE | TRUE | 0.033516 | 0.250000 |
| iPhone | SocialTrendIndex | 501.433358 | POSITIVE | POSITIVE | TRUE | 0.033516 | 0.250000 |
8. Naive four-method consensus
8. Consenso ingenuo de cuatro métodos
consensus_index = (
method_outputs
.withColumn(
"PositiveVotes",
sum(
F.when(F.col(c) == "POSITIVE", 1).otherwise(0)
for c in direction_columns
)
)
.withColumn(
"NegativeVotes",
sum(
F.when(F.col(c) == "NEGATIVE", 1).otherwise(0)
for c in direction_columns
)
)
.withColumn(
"ConsensusDirection",
F.when(F.col("PositiveVotes") > F.col("NegativeVotes"), "POSITIVE")
.when(F.col("NegativeVotes") > F.col("PositiveVotes"), "NEGATIVE")
.otherwise("CONFLICT")
)
)
Full vote table
Tabla completa de votación
| Product | ContextFactor | PearsonDirection | LagDirection | PartialDirection | ElasticNetDirection | PositiveVotes | NegativeVotes | ConsensusDirection | ConsensusConfidence | SeededDirection | ConsensusMatch |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Whole Milk | ConsumerSentiment | NEGATIVE | POSITIVE | NEGATIVE | NEGATIVE | 1 | 3 | NEGATIVE | 0.7500 | POSITIVE | FALSE |
| Whole Milk | GasolinePrice | NEGATIVE | NEGATIVE | NEGATIVE | NEGATIVE | 0 | 4 | NEGATIVE | 1.0000 | NEGATIVE | TRUE |
| Whole Milk | InflationRate | POSITIVE | POSITIVE | NEGATIVE | NEGATIVE | 2 | 2 | CONFLICT | 0.5000 | NEGATIVE | FALSE |
| Whole Milk | MiamiUnemploymentRate | POSITIVE | POSITIVE | POSITIVE | POSITIVE | 4 | 0 | POSITIVE | 1.0000 | NEGATIVE | FALSE |
| Whole Milk | MilkMarketPrice | NEGATIVE | NEGATIVE | NEGATIVE | NEGATIVE | 0 | 4 | NEGATIVE | 1.0000 | NEGATIVE | TRUE |
| iPhone | ConsumerSentiment | POSITIVE | POSITIVE | POSITIVE | POSITIVE | 4 | 0 | POSITIVE | 1.0000 | POSITIVE | TRUE |
| iPhone | FederalFundsRate | POSITIVE | NEGATIVE | NEGATIVE | NEGATIVE | 1 | 3 | NEGATIVE | 0.7500 | NEGATIVE | TRUE |
| iPhone | HolidayIndex | POSITIVE | POSITIVE | POSITIVE | POSITIVE | 4 | 0 | POSITIVE | 1.0000 | POSITIVE | TRUE |
| iPhone | InflationRate | NEGATIVE | NEGATIVE | POSITIVE | POSITIVE | 2 | 2 | CONFLICT | 0.5000 | NEGATIVE | FALSE |
| iPhone | LaunchEvent | POSITIVE | POSITIVE | POSITIVE | POSITIVE | 4 | 0 | POSITIVE | 1.0000 | POSITIVE | TRUE |
| iPhone | PromotionIntensity | POSITIVE | POSITIVE | POSITIVE | POSITIVE | 4 | 0 | POSITIVE | 1.0000 | POSITIVE | TRUE |
| iPhone | SocialTrendIndex | POSITIVE | POSITIVE | POSITIVE | POSITIVE | 4 | 0 | POSITIVE | 1.0000 | POSITIVE | TRUE |
Consensus summary
Resumen del consenso
| Metric | Value |
|---|---|
| Rules evaluated | 12.0000 |
| Correct consensus directions | 8.0000 |
| Unresolved conflicts | 2.0000 |
| Mean consensus confidence | 0.8750 |
Method reliability audit
Auditoría de confiabilidad por método
| Method | Correct | Evaluated | Accuracy |
|---|---|---|---|
| Pearson contemporaneous | 8 | 12 | 66.67 |
| Lag regularized | 10 | 12 | 83.33 |
| OLS partial effect | 9 | 12 | 75.00 |
| Elastic Net | 9 | 12 | 75.00 |
| Naive consensus | 8 | 12 | 66.67 |
Unanimous but wrong
Unánime pero equivocado
| Product | ContextFactor | ConsensusDirection | SeededDirection | ConsensusConfidence |
|---|---|---|---|---|
| Whole Milk | MiamiUnemploymentRate | POSITIVE | NEGATIVE | 1.0000 |
The consensus scored only 8/12. Whole Milk × MiamiUnemploymentRate received four POSITIVE votes with confidence 1.0, while the seeded direction was NEGATIVE. This is the laboratory’s clearest demonstration that unanimity is not calibrated truth.
El consenso obtuvo solamente 8/12. Whole Milk × MiamiUnemploymentRate recibió cuatro votos POSITIVE con confianza 1.0, mientras la dirección sembrada era NEGATIVE. Esta es la demostración más clara del laboratorio de que la unanimidad no es verdad calibrada.
9. Final numerical scoreboard
9. Marcador numérico final
| Method | Correct | Evaluated | Accuracy |
|---|---|---|---|
| Pearson contemporaneous | 8 | 12 | 66.67 |
| Lag regularized | 10 | 12 | 83.33 |
| OLS partial effect | 9 | 12 | 75.00 |
| Elastic Net | 9 | 12 | 75.00 |
| Naive consensus | 8 | 12 | 66.67 |
Best current method: regularized lag direction, 10/12 (83.33%). Best lag recovery: 7 exact, 8 within ±1 month, MAE 1.4167. Worst architectural experiment: equal-weight consensus, 8/12 despite mean confidence 0.875.
Mejor método actual: dirección con rezago regularizado, 10/12 (83.33%). Mejor recuperación de rezagos: 7 exactos, 8 dentro de ±1 mes, MAE 1.4167. Peor experimento arquitectónico: consenso con pesos iguales, 8/12 pese a una confianza media de 0.875.