Dentro de los problemas clásicos de minería de datos, podemos considerar el de predecir el abandono de clientes en una empresa que, normalmente se suele plantear para que se resuelva por diversos métodos de minería como árboles de decisión, regresiones logísticas, redes neuronales, etc.
Todos estos planteamientos tienen en común que no se estudian principalmente desde el punto de vista del tiempo trascurrido, y de que por lo tanto, elaboran una serie de modelos para tomar una serie de medidas cuando unas determinadas circunstancias se den en un cliente pero que, por lo general no están en función de la antigüedad del cliente en la empresa.
El análisis de supervivencia que vamos a ver aborda ese problema desde el punto de vista temporal, de forma que se pueda analizar también esa variable de tiempo respecto a otras variables igual que la minería clásica, sólo que esto presenta la diferencia, desde el punto de vista de la gestión de una organización, de que trata el concepto de ciclo de vida del cliente que también es necesario manejar y que, los modelos de minería generalmente, no tratan.
Muchas aplicaciones comerciales de CRM analítico, de hecho, no tratan con este tipo de algoritmos de supervivencia, porque parten del planteamiento de que la baja de un cliente siempre es evitable. Nosotros, evidentemente, no estamos de acuerdo con eso. Es más, creemos que introducir el concepto de ciclo de vida del cliente, supone aceptar que el cliente se terminará dando de baja de la empresa, y que todos los enfoques que se puedan realizar sobre conservar su lealtad, siempre terminan teniendo debilidades y áreas de mejora.
Sin polemizar, creemos que los dos enfoques (el del CRM analítico basado en modelos, y el del análisis de supervivencia) son complementarios y que deberían abordarse conjuntamente, para llegar a un mejor conocimiento desde varias perspectivas, aunque aquí vamos a hacerlo sólo respecto del segundo método.
Para empezar a estudiar el análisis de supervivencia, planteamos un problema de una empresa que en un determinado momento se percata que ha perdido el 15% de sus clientes y que desea estudiar, si realmente es debido a un ciclo natural del cliente que se ha cumplido, respecto de lo cual no puede tomar medidas, o a otra serie de circunstancias con las que sí que puede ponerse a trabajar.
La toma de datos en este tipo de problemas es muy importante, y se realiza en un determinado momento teniendo en cuenta el momento de la baja de los 45 clientes sobre los 300 posibles. Es decir, aquellos clientes que no se han dado de baja los referimos al momento actual, con la antigüedad que tengan ahora; mientras que a los que se han dado de baja, los asignamos la antigüedad que tenían en el momento de la baja.
Para operar, empezamos por cargar las librerías que necesitamos así como los datos que hemos elaborado. Las dos primeras librerías son para realizar operaciones, mientras que las otras son para dibujar los gráficos de los resultados.
library(survival)
library(broom)
library(survminer)
library(ggplot2)
library(ggfortify)
setwd(“D:/Users/Pedro/Documents/EA”)
fichero <- read.csv(“survival.csv”,sep=”;”)
La librería “survival” es la principal para realizar este tipo de análisis y la que contiene la mayor parte de las funciones que vamos a utilizar.
En primer lugar, presentamos los datos y como puede verse, tenemos la semana que nos sirve de referencia, un código para indicar el abandono de la empresa (1 se ha producido, 0 no se ha producido), el sexo, el grupo de edad, el grupo de facturación el último año, y la zona de ventas a la que pertenece.
> summary(fichero)
Semana Abandono Sexo Edad LY
Min. : 56.0 Min. :0.00 Hombre:207 Min. :20.00 Min. :130000
1st Qu.:169.8 1st Qu.:0.00 Mujer : 93 1st Qu.:40.00 1st Qu.:180000
Median :202.0 Median :0.00 Median :50.00 Median :200000
Mean :199.1 Mean :0.15 Mean :49.63 Mean :201500
3rd Qu.:231.0 3rd Qu.:0.00 3rd Qu.:60.00 3rd Qu.:220000
Max. :341.0 Max. :1.00 Max. :80.00 Max. :280000
Zona
Centro:126
Este : 21
Norte : 40
Sur :113
Puede verse que el primer dato lo tenemos en la semana 56 y el último en la semana 341, que tenemos un 15% de abandonos, que tenemos prácticamente el doble de hombres que de mujeres, comprendidos por grupos de edad entre los veintitantos y los ochentaytantos; también vemos la facturación y la zona de ventas, con una gran concentración en las zonas centro y sur.
Comenzamos por la primera instrucción: “survfit” y que es la que nos crea el modelo para analizar.
> todo <- survfit(Surv(Semana, Abandono, type=”right”) ~ 1, data = fichero)
> glance(todo)
records n.max n.start events rmean rmean.std.error median conf.low conf.high
1 300 300 300 45 275.0529 5.244137 272 262 288
Lo común que tienen que tener todos los modelos de supervivencia es una información de tiempo y una información de evento. Es decir, esta información tiene que especificarse siempre. En nuestro caso son las variables “Semana”, “Abandono con las codificaciones de (0,1) que ya hemos explicado.
También todos los modelos lo que presentan es un concepto que se conoce como “censura” y que significa que tenemos una información parcial referida a un periodo de tiempo. Cuando esa información parcial es referida al futuro, es censura por la derecha, y si es hacia el pasado, es censura por la izquierda. Lo normal en abandono de clientes es tener información completa de pasado, pero parcial del futuro, por lo que hay que indicar que la información está censurada por la derecha con la orden type=”right”, aunque la mayor parte de las veces se toma esa misma opción por defecto.
R permite que podamos ejecutar el análisis respecto de todos los datos, es decir, sin formar grupos que analizar, cosa que hacemos con la instrucción ~ 1 (El símbolo especial se genera pulsando las teclas ALT 126).
Si guardamos el resultado de la ejecución en un objeto R, podemos ver las estadísticas fundamentales del análisis de supervivencia con la orden “glance”. En este caso tenemos confirmado que son 300 clientes, con 45 eventos o abandonos, y que la media de permanencia en la empresa es de 275 semanas, mientras que la mediana es de 272, por lo que empezamos a tener una información clara sobre la esperanza de vida en la empresa con sus respectivas intervalos de confianza.
Podemos tener un conocimiento más detallado viendo los cuantiles de abandono de la empresa, para poder determinar si hay clientes con abandono prematuro sobre los que deberíamos realizar un estudio más concreto, y en donde podemos observar que sólo el 25% de los clientes se ha dado de baja antes de la semana 256.
> quantile(todo)
$quantile
25 50 75
256 272 290
Ahora podemos visualizar los datos en un gráfico de supervivencia, en donde podemos visualizar la probabilidad de supervivencia a lo largo del tiempo en donde puede verse que, prácticamente las 150 primeras semanas trascurren sin bajas.
ggsurvplot(todo)
Es importante entender este gráfico porque representa la base de todo el análisis de supervivencia y porque está totalmente condicionado tanto por los clientes que han abandonado la empresa, como por los clientes que han permanecido.
Para explicarlo mejor, creamos estas variables: el caso de Ab0, ningún cliente se da de baja, en el caso Ab1, todos los clientes se da de baja, y luego creamos dos variables en las mismas circunstancias, Ab01, todos menos el último cliente se dan de baja y en otro caso, Ab10, sólo un cliente, pero no el último, se da de baja.
> fichero$Ab0 <- 0
> fichero$Ab1 <- 1
> fichero$Ab01 <- 0
> fichero$Ab01[300] <- 1
> fichero$Ab10 <- 0
> fichero$Ab10[150] <- 1
Veamos cómo queda el gráfico de supervivencia para empezar a entenderlo.
Caso 1: Ningún cliente se da de baja, en ese caso la probabilidad de supervivencia es siempre del 100% como puede verse en la imagen 2.
ggsurvplot(survfit(Surv(Semana, Ab0, type=”right”) ~ 1, data = fichero) )
Caso 2: Todos los clientes se dan de baja, en este caso la curva de supervivencia señala el momento de la baja. Como puede observarse es una curva más posicionada a la izquierda que la de la imagen 1, en donde sólo había un 15% de bajas.
ggsurvplot(survfit(Surv(Semana, Ab1, type=”right”) ~ 1, data = fichero) )
Caso 3: Sólo el último cliente se da de baja. En este caso, vemos que la probabilidad final de supervivencia es 0, a pesar de que durante 299 casos ha sido del 100%. Esto se produce porque la probabilidad de supervivencia está en función del tiempo y en función del número de casos producido, y no sólo en función de uno de los dos.
ggsurvplot(survfit(Surv(Semana, Ab01, type=”right”) ~ 1, data = fichero) )
Caso 4: Un cliente, pero no el último, se da de baja. En este caso puede verse como la probabilidad de supervivencia, se altera ligeramente, para luego permanecer constante y terminando siendo un valor distinto de cero. Muy diferente del caso anterior, a pesar de ser muy parecido, debido a que la probabilidad de supervivencia queda condicionado por el tiempo.
ggsurvplot(survfit(Surv(Semana, Ab10, type=”right”) ~ 1, data = fichero) )
Como puede verse, en las imágenes 4 y 5. Siempre que el último valor sea una baja, la probabilidad final de supervivencia es 0, y no lo es en caso contrario. Hecho que es muy importante a la hora de calcular esperanzas de vida, como veremos más adelante.
Pero veamos con más detalle cómo se calculan las probabilidades de supervivencia, porque es lo que nos va a permitir entender este tipo de análisis. Esto puede investigando el objeto R “todo” que hemos creado.
> str(todo)
List of 13
$ n : int 300
$ time : int [1:155] 56 59 72 84 87 100 102 103 109 110 …
$ n.risk : num [1:155] 300 299 298 297 296 295 294 292 290 289 …
$ n.event : num [1:155] 1 0 0 0 0 0 0 0 0 0 …
$ n.censor : num [1:155] 0 1 1 1 1 1 2 2 1 1 …
$ surv : num [1:155] 0.997 0.997 0.997 0.997 0.997 …
$ type : chr “right”
$ std.err : num [1:155] 0.00334 0.00334 0.00334 0.00334 0.00334 …
$ upper : num [1:155] 1 1 1 1 1 1 1 1 1 1 …
$ lower : num [1:155] 0.99 0.99 0.99 0.99 0.99 …
$ conf.type: chr “log”
$ conf.int : num 0.95
$ call : language survfit(formula = Surv(Semana, Abandono, type = “right”) ~ 1, data = fichero)
– attr(*, “class”)= chr “survfit”
En este caso puede verse que a pesar de que tenemos 300 clientes, sólo tenemos 155 momentos distintos en donde se produce o bien una permanencia o bien un abandono, y son esos 155 momentos los que se estudian en la variable “time”.
También puede verse que en el sub-objeto R “todo$surv” tenemos guardadas los 155 valores distintos de las probabilidades, que en el sub-objeto “todo$n.event” tenemos si en ese momento se ha producido un suceso de permanencia o abandono, que en el sub-objeto “todo$n.risk” el número de clientes que nos quedan después de ese momento. Y son con esas variables con las que vamos a trabajar.
Para ello, pasamos todas las variables que nos interesan a una matriz, y empezamos la exploración.
estudio <- cbind(todo$time,todo$n.risk,todo$n.event,todo$surv)
>head(estudio)
[,1] [,2] [,3] [,4]
[1,] 56 300 1 0.9966667
[2,] 59 299 0 0.9966667
[3,] 72 298 0 0.9966667
[4,] 84 297 0 0.9966667
[5,] 87 296 0 0.9966667
[6,] 100 295 0 0.9966667
En este caso vemos que en la semana 56 (columna 1), se ha producido una baja por lo que la probabilidad de supervivencia, teniendo en cuenta que es sólo una baja sobre 300 clientes es de:
299/300 = 0,9966667.
En la semana 59 (fila 2) no se produce ninguna baja, por lo que la probabilidad de supervivencia, no queda afecta aunque se calcularía como:
Probabilidad anterior * (1 – (Bajas habidas / Clientes que aún quedan por calcular))
Es decir 0,996667 * (1 – (0/299)) = 0,996667
Si pasamos ahora ver la siguiente baja, vemos que es la que se produce en la semana 173.
> estudio[55:58,]
[,1] [,2] [,3] [,4]
[1,] 171 222 0 0.9966667
[2,] 172 216 0 0.9966667
[3,] 173 215 1 0.9920310
[4,] 175 214 0 0.9920310
En este caso, el valor de la probabilidad de supervivencia se calcularía, con 215 clientes que aún nos quedan, así:
0,996667 * (1 – (1/215)) = 0,996667 * 0,995349 = 0,992031
Siguiendo así, podemos ver en el caso de la semana 277, en donde se han producido 2 bajas que la probabilidad de supervivencia queda calculada así:
> estudio[140:145,]
[,1] [,2] [,3] [,4]
[1,] 276 17 0 0.4840808
[2,] 277 16 2 0.4235707
[3,] 278 14 0 0.4235707
[4,] 279 13 1 0.3909883
[5,] 281 12 0 0.3909883
[6,] 284 11 1 0.3554439
Valor semana 277 = 0,4840808 * (1 – (2/16)) = 0,4840808 * 0,875 = 0,4235707
Lo que significa que con los datos que tenemos, la probabilidad de que un cliente permanezca en la empresa en la semana 277 de antigüedad es del 42,35%.
Con esto puede entenderse que si el último cliente que tenemos tiene una baja, la probabilidad final valdrá cero, mientras que si no lo fuera, significaría que la probabilidad de que un cliente siga en la empresa en la semana 12.879, por ejemplo que es más de 2 siglos, no sería nula, si no que mantendría el último valor de la probabilidad que hayamos obtenido por este procedimiento de cálculo, lo que es absurdo.
> estudio[150:155,]
[,1] [,2] [,3] [,4]
[1,] 299 6 1 0.2073423
[2,] 314 5 0 0.2073423
[3,] 316 4 0 0.2073423
[4,] 317 3 1 0.1382282
[5,] 319 2 0 0.1382282
[6,] 341 1 1 0.0000000
Por todo ello, es muy importante entender que las probabilidades de supervivencia, son probabilidades condicionadas a que se alcance una cierta antigüedad y que, por lo tanto, dependen del tiempo, así como del número de clientes que hayan permanecido o abandonado la empresa.
Si repasamos ahora, porqué son tan diferentes los datos de las imágenes 4 y 5, tenemos que concluir que esa diferencia es debida a la “censura por la derecha”, es decir a que no tenemos datos del futuro (desconocimiento parcial), pero también es debida a la manera de calcular las probabilidades de supervivencia según los datos de que disponemos. En una caso las probabilidades finales de supervivencia son nulas, mientras que en el otro superan el 99%, de ahí que tengamos que tener cuidado a la hora de seleccionar los datos con los que trabajamos, para que las conclusiones a las que lleguemos tengan sentido.
Toda esta información sirve por ejemplo, para decidir el coste adecuado tanto de adquisición, como de mantenimiento de un cliente. Si por ejemplo, el beneficio esperado por cliente es 10 euros a la semana, como sabemos que la esperanza de vida media es de 275,05 semanas, entonces el beneficio a lo largo de la vida del cliente es de 275,05 semanas * 10 € / semana = 2.750,5 euros. Por lo que todo coste para retener a un cliente que supere esa cantidad, no tendría lógica, puesto que provocaría pérdidas.
Al mismo tiempo, tenemos que si la probabilidad de supervivencia en la semana 300 es del 21%, cualquier decisión estratégica que tenga ese horizonte, debe tenerlo en cuenta para, o bien para tener en cuenta la caída de ingresos, o bien para planificar la renovación de la cartera de clientes.
Relacionado con todo esto, se presenta el concepto de media restringida, o “rmean”, que representa el cálculo de la vida media, planteando un horizonte máximo, es decir, imaginemos que estamos programando a 105 semanas o dos años. Esto se realiza con ayuda de la orden “print” con el parámetro “rmean”
> print(todo, rmean=105)
Call: survfit(formula = Surv(Semana, Abandono, type = “right”) ~ 1,
data = fichero)
n events *rmean *se(rmean) median 0.95LCL 0.95UCL
300.000 45.000 104.837 0.163 272.000 262.000 288.000
* restricted mean with upper limit = 105
En este caso, vemos que con ese límite, la esperanza de vida es 104,83 semanas y que representa el área de la curva de la imagen 6, que está bajo la curva de probabilidad y a la izquierda de la fecha azul y que tiene un sentido diferenciador cuando se comparan subgrupos dentro de la muestra, mucho más que cuando se ve de manera aislada.
Para comprender mejor el sentido de media restringida, examinemos la supervivencia según la zona, viendo primero las 4 zonas de ventas, según sus curvas de probabilidad de supervivencia.
zona <- survfit(Surv(Semana, Abandono, type=”right”) ~ Zona, data = fichero)
ggsurvplot(zona)
> print(zona,rmean=105)
Call: survfit(formula = Surv(Semana, Abandono, type = “right”) ~ Zona,
data = fichero)
n events *rmean *se(rmean) median 0.95LCL 0.95UCL
Zona=Centro 126 11 105 0.000 341 NA NA
Zona=Este 21 2 105 0.000 299 NA NA
Zona=Norte 40 5 105 0.000 272 257 NA
Zona=Sur 113 27 105 0.432 265 256 284
* restricted mean with upper limit = 105
> print(zona,rmean=260)
Call: survfit(formula = Surv(Semana, Abandono, type = “right”) ~ Zona,
data = fichero)
n events *rmean *se(rmean) median 0.95LCL 0.95UCL
Zona=Centro 126 11 252 2.41 341 NA NA
Zona=Este 21 2 256 3.32 299 NA NA
Zona=Norte 40 5 256 1.91 272 257 NA
Zona=Sur 113 27 249 2.95 265 256 284
* restricted mean with upper limit = 260
> print(zona,rmean=2600)
Call: survfit(formula = Surv(Semana, Abandono, type = “right”) ~ Zona,
data = fichero)
n events *rmean *se(rmean) median 0.95LCL 0.95UCL
Zona=Centro 126 11 307 9.42 341 NA NA
Zona=Este 21 2 292 7.02 299 NA NA
Zona=Norte 40 5 263 3.66 272 257 NA
Zona=Sur 113 27 261 4.87 265 256 284
* restricted mean with upper limit = 2600
Como puede verse, las decisiones que se puedan tomar con un horizonte a 105 semanas, no van a tener repercusiones entre unas zonas de ventas y otras. Cosa que no sucede cuando el horizonte es de 260 semanas, o cuando no hay horizonte final, puesto que el valor del rmean es diferente.
También se puede realizar este estudio cuando se combinan más factores, para examinar así la esperanza de supervivencia. En el caso que viene a continuación lo hacemos combinando las variables Edad, Sexo, Zona, examinando en cuáles de todas las combinaciones tenemos menor esperanza de vida para nuestros clientes, viendo también porqué se produce ese valor e identificando donde se producen los mayores abandonos.
>especial <- survfit(Surv(Semana, Abandono, type=”right”) ~ Edad + Sexo + Zona, data = fichero)
>summary(print(especial,rmean=260))$table -> estudio2
>head(estudio2[order(estudio2[,5]),c(1:6)])
records n.max n.start events *rmean *se(rmean)
Edad=70, Sexo=Hombre, Zona=Centro 6 6 6 1 227.0000 0.000000
Edad=70, Sexo=Hombre, Zona=Sur 7 7 7 1 232.6667 17.418594
Edad=50, Sexo=Mujer , Zona=Sur 18 18 18 5 235.0312 11.638114
Edad=60, Sexo=Mujer , Zona=Centro 4 4 4 1 236.0000 12.727922
Edad=60, Sexo=Hombre, Zona=Centro 16 16 16 2 236.5000 6.080193
Edad=60, Sexo=Hombre, Zona=Este 7 7 7 1 239.5000 10.253048
>estudio2[estudio2[,4]>2,c(1:6)]
records n.max n.start events *rmean *se(rmean)
Edad=40, Sexo=Hombre, Zona=Centro 24 24 24 3 246.5208 4.801243
Edad=40, Sexo=Hombre, Zona=Sur 14 14 14 3 243.5000 5.356071
Edad=40, Sexo=Mujer , Zona=Sur 10 10 10 3 254.0000 0.000000
Edad=50, Sexo=Hombre, Zona=Sur 28 28 28 9 243.0529 4.451569
Edad=50, Sexo=Mujer , Zona=Sur 18 18 18 5 235.0312 11.638114
Edad=60, Sexo=Hombre, Zona=Sur 18 18 18 3 254.0000 0.000000
También con la orden “survdiff”, podemos realizar un test de hipótesis no paramétrico que nos diga si la diferencia de la probabilidad de supervivencia entre subgrupos es significativa o no. En este caso lo sería, al obtener un p-value < 0,05, experimentando esas diferencias en las zonas Centro y Sur, que sería en donde deberíamos de realizar un estudio más en profundidad.
> survdiff(Surv(Semana, Abandono, type=”right”) ~ Zona, data = fichero)
Call:
survdiff(formula = Surv(Semana, Abandono, type = “right”) ~ Zona,
data = fichero)
N Observed Expected (O-E)^2/E (O-E)^2/V
Zona=Centro 126 11 18.57 3.0862 5.6607
Zona=Este 21 2 3.16 0.4251 0.4672
Zona=Norte 40 5 5.48 0.0413 0.0502
Zona=Sur 113 27 17.79 4.7618 8.2159
Chisq= 8.8 on 3 degrees of freedom, p= 0.0326
Observaciones.
1.- En otros análisis de supervivencia, en donde se puede considerar constante la baja de individuos a lo largo del tiempo, es decir, en modelos de tipo biológico o de tipo industrial, en donde tratan conceptos sobre supervivencia de bacterias o durabilidad de componentes electrónicos, se realizan el llamado estudio Cox, en donde, igual que en la regresión logística estudia la influencia de cada factor en la probabilidad de supervivencia.
Esto se realiza así.
> zona.cosph <- coxph(Surv(Semana, Abandono, type=”right”) ~ Zona, data = fichero)
> summary(zona.cosph)
Call:
coxph(formula = Surv(Semana, Abandono, type = “right”) ~ Zona,
data = fichero)
n= 300, number of events= 45
coef exp(coef) se(coef) z Pr(>|z|)
ZonaEste 0.09848 1.10349 0.77778 0.127 0.89924
ZonaNorte 0.50605 1.65873 0.56384 0.898 0.36944
ZonaSur 1.00816 2.74056 0.37490 2.689 0.00716 **
Y para el caso significativo (p-value < 0,05) de la Zona Sur significaría que la probabilidad de abandona se multiplica por 2,74 por el hecho de no estar a estar en la zona Sur, pero repetimos, si tuviera una tasa constante de abandonos a lo largo del tiempo, que en el caso de abandono de clientes casi nunca se cumple.
2.- Este mismo análisis conviene repetirlo pasado un cierto tiempo, para comprobar si las medidas que se han tomado han conseguido alargar el ciclo de vida del cliente. En ese caso, conviene tomar nuevos datos y estudiarlos conjuntamente con los antiguos, indicando en una variable el tipo de estudio que es. Después se puede realizar el análisis de las probabilidades de supervivencia de forma segmentada, igual que lo hemos hecho nosotros con respecto a las zonas, y ver si existen diferencias significativas y en qué circunstancias se producen con ayuda de la orden “survdiff”.
Esto puede realizarse así, introduciendo la salida de la instrucción en un objeto R, y luego transformando ese objeto en una variable “matriz” con la información que nos interesa para poder operar con ella, viendo en donde se han producido las principales diferencias.
> survdiff(Surv(Semana, Abandono, type=”right”) ~ Edad + Sexo, data = fichero) -> fr
> summary(fr)
Length Class Mode
n 12 table numeric
obs 12 -none- numeric
exp 12 -none- numeric
var 144 -none- numeric
chisq 1 -none- numeric
call 3 -none- call
> cbind(unlist(fr[1]),unlist(fr[2]),unlist(fr[3])) -> fr2
> fr2 <- cbind(fr2,(fr2[,2]-fr2[,3])^2/fr2[,3])
> fr2[fr2[,4]>1,]
[,1] [,2] [,3] [,4]
n.Edad=30, Sexo=Hombre 16 0 1.515006 1.515006
n.Edad=30, Sexo=Mujer 7 0 1.056405 1.056405
n.Edad=60, Sexo=Hombre 49 7 4.172307 1.916409
n.Edad=60, Sexo=Mujer 16 4 1.883192 2.379404
n.Edad=70, Sexo=Hombre 15 3 1.486155 1.542050
3.- Este tipo de análisis es NO paramétrico, y se ha impuesto sobre los análisis paramétricos con funciones Weibull o exponenciales. Aunque en entornos biológicos o industriales, se aplican con más frecuencia que en márketing, análisis de supervivencia paramétricos. En estos casos, hay que explicar en el modelo qué rol juega cada parámetro de la función que ajusta la probabilidad de supervivencia, aunque repetimos, en el caso de abandono de clientes en una empresa, no suele hacerse, siendo el análisis no paramétrico más aplicable y más sencillo de explicar.
Autor: Pedro José Jiménez, profesor del Máster en Big Data y Business Intelligence