19  Un caso especial: MaxDiff (Best-Worst Scaling)

Published

June 29, 2026

19.1 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) (Louviere et al. 2015).

19.2 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 (Louviere et al. 2015).

19.3 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 (McFadden 1974). 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.

19.4 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.

19.4.1 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.

19.4.2 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:

Code
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)
  resp_id task_id alt_id                   item
1       1       1      1           Chat_en_vivo
2       1       1      2 Atencion_personalizada
3       1       1      3          Respuesta_24h
4       1       1      4      Multiples_canales
5       1       2      1 Atencion_personalizada
6       1       2      2          Respuesta_24h
7       1       2      3              App_movil
8       1       2      4      Multiples_canales
Code
# 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)
# A tibble: 8 × 6
  resp_id task_id obs_id alt_id item                    best
    <int>   <int>  <int>  <int> <chr>                  <int>
1       1       1      1      1 Chat_en_vivo               0
2       1       1      1      2 Atencion_personalizada     0
3       1       1      1      3 Respuesta_24h              0
4       1       1      1      4 Multiples_canales          1
5       1       2      2      1 Atencion_personalizada     0
6       1       2      2      2 Respuesta_24h              1
7       1       2      2      3 App_movil                  0
8       1       2      2      4 Multiples_canales          0

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:

Code
maxdiff_data$item <- factor(maxdiff_data$item, levels = service_items)

19.4.3 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:

Code
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)
=================================================

Model estimated on: lu. jun. 29 16:23:46 2026 

Using logitr version: 1.1.3 

Call:
logitr::logitr(data = maxdiff_data, outcome = "best", obsID = "obs_id", 
    pars = "item")

Frequencies of alternatives:
      1       2       3       4 
0.24000 0.25556 0.26000 0.24444 

Exit Status: 3, Optimization stopped because ftol_rel or ftol_abs was reached.
                                
Model Type:    Multinomial Logit
Model Space:          Preference
Model Run:                1 of 1
Iterations:                   13
Elapsed Time:           0h:0m:0s
Algorithm:        NLOPT_LD_LBFGS
Weights Used?:             FALSE
Robust?                    FALSE

Model Coefficients: 
                           Estimate Std. Error  z-value  Pr(>|z|)    
itemChat_en_vivo           -0.44245    0.11533  -3.8364 0.0001248 ***
itemReembolso_rapido        0.73034    0.10348   7.0581 1.688e-12 ***
itemAtencion_personalizada -1.19469    0.14178  -8.4266 < 2.2e-16 ***
itemApp_movil              -2.10029    0.19922 -10.5426 < 2.2e-16 ***
itemMultiples_canales      -1.27747    0.14593  -8.7542 < 2.2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
                                     
Log-Likelihood:          -968.8518575
Null Log-Likelihood:    -1247.6649250
AIC:                     1947.7037150
BIC:                     1971.7157000
McFadden R2:                0.2234679
Adj McFadden R2:            0.2194604
Number of Observations:   900.0000000

19.4.4 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:

Code
maxdiff_coefs <- coef(maxdiff_model)
maxdiff_coefs
          itemChat_en_vivo       itemReembolso_rapido 
                -0.4424511                  0.7303411 
itemAtencion_personalizada              itemApp_movil 
                -1.1946921                 -2.1002916 
     itemMultiples_canales 
                -1.2774695 
Code
maxdiff_ranking <- data.frame(
  item    = names(maxdiff_coefs),
  utility = round(unname(maxdiff_coefs), 2)
) |>
  dplyr::arrange(dplyr::desc(utility))

maxdiff_ranking
                        item utility
1       itemReembolso_rapido    0.73
2           itemChat_en_vivo   -0.44
3 itemAtencion_personalizada   -1.19
4      itemMultiples_canales   -1.28
5              itemApp_movil   -2.10
Code
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()
Figure 19.1: Ranking de prioridades de mejoras del servicio de atención al cliente

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.

TipCuá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.

19.5 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.