estadística
ciencia de datos
2025
Author

José Luis Cañadas Reche

Published

August 15, 2025

Listening

En un tiempo no muy lejano del cual estoy intentando olvidarme oí hablar de lo que yo llamo “gatillos” o como les gusta decir a algunos “triggers” ( lo de gatillos viene de derivar triggers a tigres y luego a gatillos, que encima tiene que ver con disparar)

Es una cosa muy sencilla, si se da un eventoA entonces mando a la gente que tiene ese evento a campaña 1, y se da eventoB mando a esos a campaña 2.

Hasta aquí todo más o menos bien, pero como pensaría cualquier persona normal, ¿ si tener el eventoA o tener el eventoB aumentan la probabilidad de comprar el mismo producto, por qué no meter esos eventos en un modelo, de forma que pille las interacciones y así seleccionar a los más propensos a comprar el producto? Pues os prometo que me miraban con cara de estupor, sin entender el por qué eso iba a ser mejor. Visto con cierta distancia, la verdad es que no creo que no se entendiera, sino que simplemente no se quería cambiar nada y que cualquier propuesta que viniera de determinada gente, simplemente se ignoraba o se consideraba errónea. Un sinsentido.

Un poco de código para ejemplificar.

Generamos unos datos dónde tenemos EventoA (1,0), EventoB (1,0) y una variable target que está relacionada positivamente con ambos eventos, por lo cual es lógico pensar que las observaciones que tienen ambos eventos estarán aún más relacionadas con la target.

Show the code
library(dplyr)
set.seed(123)

n <- 1000

Evento1 <- rbinom(n, size = 1, prob = 0.7) 
Evento2 <- rbinom(n, size = 1, prob = 0.6) 

p_target <- ifelse(Evento1 == 1, 0.7, 0.2)

p_target <- p_target + ifelse(Evento2 == 1, 0.3, -0.05)
p_target <- pmin(pmax(p_target, 0.01), 0.99) # limitar entre 0 y 1

# Simular target 
target <- rbinom(n, size = 1, prob = p_target)

df <- data.frame(Evento1, Evento2, target)

head(df)
#>   Evento1 Evento2 target
#> 1       1       1      1
#> 2       0       1      0
#> 3       1       1      1
#> 4       0       0      0
#> 5       0       0      0
#> 6       1       1      1

Comprobamos que efectivamente es así

Show the code
# Comprobar proporciones
prop.table(table(df$target, df$Evento1), margin = 2)
#>    
#>             0         1
#>   0 0.6067797 0.1531915
#>   1 0.3932203 0.8468085
prop.table(table(df$target, df$Evento2), margin = 2)
#>    
#>             0         1
#>   0 0.5077720 0.1482085
#>   1 0.4922280 0.8517915


df |>
  group_by(Evento1, Evento2) |>
  summarise(
    mean(target)
  )
#> # A tibble: 4 × 3
#> # Groups:   Evento1 [2]
#>   Evento1 Evento2 `mean(target)`
#>     <int>   <int>          <dbl>
#> 1       0       0          0.179
#> 2       0       1          0.525
#> 3       1       0          0.620
#> 4       1       1          0.991

Y como no podía ser de otra manera, la interacción (tener ambos eventos) tiene una mayor proporción de target=1 que cada evento por separado

Pues simplemente haber hecho un modelo donde entraran los “gatillos” habría sido mucho mejor que simplemente considerar por separado.

Show the code
m_eff_princ <- glm(target ~ Evento1 + Evento2, data = df, family = binomial)
m_eff_interacc <- glm(target ~ Evento1 * Evento2, data = df, family = binomial)


summary(m_eff_princ)
#> 
#> Call:
#> glm(formula = target ~ Evento1 + Evento2, family = binomial, 
#>     data = df)
#> 
#> Coefficients:
#>             Estimate Std. Error z value Pr(>|z|)    
#> (Intercept)  -2.3737     0.2370  -10.02   <2e-16 ***
#> Evento1       3.0308     0.2338   12.96   <2e-16 ***
#> Evento2       2.7037     0.2313   11.69   <2e-16 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> (Dispersion parameter for binomial family taken to be 1)
#> 
#>     Null deviance: 1198.89  on 999  degrees of freedom
#> Residual deviance:  792.41  on 997  degrees of freedom
#> AIC: 798.41
#> 
#> Number of Fisher Scoring iterations: 5

summary(m_eff_interacc)
#> 
#> Call:
#> glm(formula = target ~ Evento1 * Evento2, family = binomial, 
#>     data = df)
#> 
#> Coefficients:
#>                 Estimate Std. Error z value Pr(>|z|)    
#> (Intercept)      -1.5261     0.2467  -6.185 6.19e-10 ***
#> Evento1           2.0175     0.2763   7.300 2.87e-13 ***
#> Evento2           1.6245     0.2877   5.646 1.64e-08 ***
#> Evento1:Evento2   2.5546     0.5921   4.314 1.60e-05 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> (Dispersion parameter for binomial family taken to be 1)
#> 
#>     Null deviance: 1198.89  on 999  degrees of freedom
#> Residual deviance:  767.55  on 996  degrees of freedom
#> AIC: 775.55
#> 
#> Number of Fisher Scoring iterations: 7

Siiii, ya sé que es un post muy tonto y fácil, pero es que muchas veces me encuentro con gente que no sabe qué es una interacción (aunque usen constantemente xgboost, que es una glorificación de la interacción).