# Un caso especial: MaxDiff (Best-Worst Scaling)
```{r}
#| echo: false
#| message: false
#| warning: false
source("script.R")
```
## Introducción: priorizar elementos, no productos completos
Los capítulos anteriores han desarrollado el análisis conjoint en sus dos
grandes variantes —tradicional y basado en elecciones (CBC)— centradas siempre
en **productos completos**, descompuestos en atributos y niveles combinables
entre sí. Existe, sin embargo, una pregunta de investigación distinta y muy
frecuente en marketing: **priorizar una lista de elementos** —beneficios de un
producto, mensajes publicitarios, razones de compra, características deseadas—
sin que esos elementos formen parte de un perfil de producto combinable. Para
este tipo de problema, la técnica de referencia es el **MaxDiff** (*Maximum
Difference Scaling*), también conocido como **escalamiento del mejor-peor**
(*Best-Worst Scaling*) [@Louviere2015].
## La lógica del MaxDiff
En una tarea MaxDiff, se presenta al encuestado un subconjunto de elementos
(típicamente entre 4 y 6) extraído de una lista más amplia, y se le pide que
señale, dentro de ese subconjunto, cuál considera el **mejor** (o más
importante) y cuál el **peor** (o menos importante). Esta tarea se repite varias
veces con distintos subconjuntos, de modo que cada elemento de la lista completa
aparece varias veces a lo largo del cuestionario, en distintas combinaciones.
La elección simultánea del mejor y el peor elemento aporta más información por
tarea que una simple clasificación o valoración con escala Likert, y evita un
sesgo habitual de las escalas de valoración: la tendencia de algunos encuestados
a puntuar todo de forma uniformemente alta o uniformemente baja, lo que
dificulta diferenciar la importancia relativa real de cada elemento
[@Louviere2015].
## MaxDiff como caso especial de modelo logit condicional
La razón por la que el MaxDiff se presenta como cierre de este bloque de
capítulos, y no como una técnica completamente nueva, es que **su estructura
estadística subyacente es exactamente la misma del CBC** desarrollado
anteriormente: cada elección del "mejor" elemento dentro de un subconjunto es
formalmente idéntica a una tarea de elección discreta entre varias alternativas,
con la misma teoría de la utilidad aleatoria de McFadden como fundamento
[@McFadden1974]. Esto significa que el armazón teórico y los mismos paquetes
—`mlogit` o `logitr`— desarrollados en los capítulos anteriores para el CBC son
directamente aplicables al MaxDiff, con una única adaptación: la estructura de
los datos.
Una tarea MaxDiff con $k$ elementos en el subconjunto se descompone en **dos
modelos logit condicionales**: uno sobre la elección del elemento "mejor"
(tratando cada elemento del subconjunto como una alternativa, igual que en el
CBC) y otro, simétrico, sobre la elección del elemento "peor" entre los $k$
elementos restantes excluyendo al ya seleccionado como mejor. Este capítulo
desarrolla el primero de los dos modelos, que es habitualmente el de mayor
interés práctico.
## Aplicación práctica: priorización de atributos de servicio al cliente
Se desarrolla el caso de una empresa de telecomunicaciones que quiere priorizar,
entre seis posibles mejoras de su servicio de atención al cliente, cuáles
deberían implementarse primero según las preferencias de sus clientes.
### Objetivo de la investigación
> **Objetivo**: estimar un modelo MaxDiff que priorice seis posibles mejoras del
> servicio de atención al cliente, a partir de las elecciones de "mejor"
> elemento realizadas por una muestra de clientes en sucesivas tareas de
> comparación.
### Preparación de los datos
Se simulan los datos de 150 encuestados, cada uno respondiendo a 6 tareas
MaxDiff, mostrando en cada una un subconjunto de 4 de los 6 atributos de
servicio evaluados:
```{r}
#| echo: true
#| message: false
set.seed(33)
service_items <- c("Respuesta_24h", "Chat_en_vivo", "Reembolso_rapido",
"Atencion_personalizada", "App_movil", "Multiples_canales")
# True (simulated) preference weights for each service attribute
true_maxdiff_utilities <- c(
Respuesta_24h = 1.2,
Chat_en_vivo = 0.8,
Reembolso_rapido = 1.8,
Atencion_personalizada = 0.3,
App_movil = -0.2,
Multiples_canales = 0.1
)
n_respondents_md <- 150
n_tasks_md <- 6
n_shown_md <- 4
# Build the MaxDiff design: for each respondent and task, randomly select
# 4 of the 6 items to display
maxdiff_design <- purrr::map_dfr(1:n_respondents_md, function(resp) {
purrr::map_dfr(1:n_tasks_md, function(task) {
shown_items <- sample(service_items, n_shown_md)
data.frame(
resp_id = resp,
task_id = task,
alt_id = 1:n_shown_md,
item = shown_items
)
})
})
head(maxdiff_design, 8)
```
```{r}
#| echo: true
# Add a unique observation identifier, the utility of each item, and a
# random utility component to simulate plausible "best" choices
maxdiff_data <- maxdiff_design |>
dplyr::mutate(obs_id_chr = paste(resp_id, task_id, sep = "_")) |>
dplyr::mutate(utility = true_maxdiff_utilities[item] + rnorm(dplyr::n(), 0, 1))
maxdiff_data$obs_id <- as.integer(factor(maxdiff_data$obs_id_chr))
# Within each task, the item with the highest simulated utility is chosen as "best"
maxdiff_data <- maxdiff_data |>
dplyr::group_by(obs_id) |>
dplyr::mutate(best = as.integer(utility == max(utility))) |>
dplyr::ungroup() |>
dplyr::select(resp_id, task_id, obs_id, alt_id, item, best)
head(maxdiff_data, 8)
```
Como en los capítulos anteriores, la variable `item` se convierte explícitamente
a `factor`, fijando el orden de sus niveles, para garantizar que el modelo
nombre los coeficientes con las etiquetas reales de cada elemento:
```{r}
#| echo: true
maxdiff_data$item <- factor(maxdiff_data$item, levels = service_items)
```
### Estimación del modelo "mejor"
Se estima un modelo logit condicional sobre la elección del elemento "mejor",
tratando cada uno de los seis elementos de servicio como una variable dummy (sin
intercepto). Como en los capítulos anteriores, se fuerza explícitamente
`contr.treatment` para garantizar que los coeficientes se nombren con las
etiquetas reales de cada elemento, con independencia de la configuración de
contrastes de la sesión:
```{r}
#| echo: true
#| message: false
old_contrasts <- options("contrasts")
options(contrasts = c("contr.treatment", "contr.poly"))
maxdiff_model <- logitr::logitr(
data = maxdiff_data,
outcome = "best",
obsID = "obs_id",
pars = "item"
)
options(old_contrasts)
summary(maxdiff_model)
```
### Interpretación: el ranking de prioridades
Los coeficientes estimados se interpretan directamente como la utilidad relativa
de cada elemento frente a la categoría de referencia (el primer nivel del
factor, `Respuesta_24h`), y permiten construir un ranking claro de prioridades:
```{r}
#| echo: true
maxdiff_coefs <- coef(maxdiff_model)
maxdiff_coefs
```
```{r}
#| echo: true
maxdiff_ranking <- data.frame(
item = names(maxdiff_coefs),
utility = round(unname(maxdiff_coefs), 2)
) |>
dplyr::arrange(dplyr::desc(utility))
maxdiff_ranking
```
```{r}
#| label: fig-maxdiff-ranking
#| fig-cap: Ranking de prioridades de mejoras del servicio de atención al cliente
#| echo: true
ggplot2::ggplot(maxdiff_ranking, ggplot2::aes(x = reorder(item, utility), y = utility)) +
ggplot2::geom_col(fill = "#076fa2") +
ggplot2::coord_flip() +
ggplot2::labs(x = NULL, y = "Utilidad relativa (referencia: Respuesta_24h)") +
ggplot2::theme_minimal()
```
El resultado es un ranking directamente accionable: "Reembolso rápido" emerge
como la prioridad más valorada por los clientes, muy por encima de "App móvil",
que resulta ser, de hecho, el atributo menos valorado del conjunto evaluado —una
conclusión que orienta directamente la hoja de ruta de mejoras del servicio.
::: callout-tip
## Cuándo usar MaxDiff frente a CBC
El MaxDiff es la técnica adecuada cuando el objetivo de investigación es
**priorizar una lista de elementos no combinables** (beneficios, mensajes,
razones de compra, características deseadas), mientras que el CBC es la técnica
adecuada cuando el objetivo es modelar la elección entre **productos
completos**, definidos por la combinación de varios atributos con sus
respectivos niveles —incluyendo, de forma crucial, el atributo precio, que
permite calcular la disposición a pagar. Ambas comparten el mismo fundamento
estadístico de la utilidad aleatoria, lo que explica que los mismos paquetes de
estimación (`mlogit`, `logitr`) sean aplicables a ambas con una sencilla
adaptación de la estructura de los datos.
:::
## Conclusión del bloque de modelos de elección discreta
A lo largo de estos cuatro capítulos se han presentado tres variantes del
análisis de preferencias del consumidor, unidas por un fundamento estadístico
común. El **conjoint tradicional**, basado en la valoración de perfiles
completos y estimado mediante regresión, representa el enfoque original e
históricamente anterior. El **análisis conjoint basado en elecciones (CBC)**,
fundamentado en la teoría de la utilidad aleatoria de McFadden y estimado
mediante modelos logit condicionales, constituye hoy el estándar de la
industria, con capacidad para calcular la importancia relativa de los atributos,
la disposición a pagar y simular cuotas de mercado entre configuraciones de
producto competidoras. El paquete `cbcTools` complementa el CBC en su fase de
diseño experimental, mientras que `logitr` ofrece una alternativa de estimación
con parametrización directa en espacio de disposición a pagar. El **MaxDiff**,
como caso especial de la misma familia de modelos logit, resuelve el problema
distinto de priorizar una lista de elementos no combinables.
Con esto se cierra el contenido del libro dedicado a las técnicas de análisis
aplicadas a la investigación de mercados, desde la preparación de un fichero de
encuesta hasta los modelos de elección discreta que sustentan decisiones
estratégicas de producto, precio y priorización en la práctica profesional del
sector.