Disponemos de una recopilación de datos (Montgomery & Peck, 1982) relativos al tiempo de entrega (delTime) de máquinas expendedoras (desde que se gestiona la compra), junto con lo que vamos a entender como el número de productos demandados (n.prod) y la distancia entre el proveedor y el comprador (distance).
data(delivery, package="robustbase")
Ponte en el lugar del cliente que solicita un pedido a la empresa: ¿cuáles serían tus expectativas de calidad relativas a los tiempos de entrega?
Las expectativas de un cliente respecto a los tiempos de entrega principalmente son:
Es posible que la empresa tenga problemas para cumplir con los intereses de sus clientes. Investiga esta cuestión desde un punto de vista meramente descriptivo,a través de las cuestiones a continuación, y expresa tus conclusiones exclusivamente respondiendo a la pregunta ¿qué problemas parece tener la empresa para cumplir con las expectativas de sus clientes?
library(ggplot2)
library(plotly)
fig<-ggplot(delivery,aes(n.prod))+
geom_histogram(bins = 15,fill='#D05147',color='#08103E')+
xlab('Número de Productos')+
ylab('Número de veces pedidos')
p<-plotly::ggplotly(fig)
p
El gráfico (histograma) lo que nos muestra es el número de productos pedidos, y las barras nos indican dicho producto cuantas veces ha sido pedido, y como observamos que la mayoría de los productos pedidos son por debajo de 10(hay más barras en ese rango) y lo podemos observar en el siguiente gráfico:
library(dplyr)
mayor10<- length(which(delivery$n.prod > 10))
menorigual10<- length(which(delivery$n.prod <= 10))
conteo<- data.frame(pedidos=c(mayor10,menorigual10),
Productos=c('>10','<=10'))
ggplot(conteo,aes(Productos,pedidos))+
geom_bar(stat = 'identity',aes(fill =Productos),width = 0.5)+
geom_text(aes(label=pedidos),vjust=-0.3)+
xlab('Número de productos')+
ylab('total pedidos')
Entonces, las máquinas demandadas en cada pedido no las podemos dar como una media aritmética, que es sumar todos los productos pedidos y dividir por el total número de pedidos, porque vemos que en el gráfico hay 4 pedidos que pueden elevar el número de máquinas demandas debido a que estos pedidos tienen números de maquinas demandas muy superiores al otro grupo, en cual el número de máquinas demandadas es menor o igual a 10. ¿Elevar la media? Este concepto se ilustra en las siguientes imágenes:
La media aritmética podemos entenderla por ejemplo que tenemos una urbanización con 3 edificios(grupos) y que en cada grupo(edifico) hay un cierto número de cajas(altura) entonces la media consiste en que en todos los grupos tengamos el mismo número de cajas y lo podemos entenderlo como en la imagen mover una caja verde a un grupo azul para que las torres estén a una altura similar y como vemos aquí sólo tuvimos que mover una caja, por lo tanto la altura de los 3 grupos(edificios) se puede resumir bien por la media, que dice que la altura de edificios en dicha urbanización es de 3 cajas porque azul tenían 2 cajas ,naranja 3 y verde 4 y la media, que es 3, resume bien la altura de los edificos de la urbanización.
Lo mismo pasa en nuestro dataset: hay un grupo que tiene el número de pedidos bajos y otro muy altos, por lo tanto, el grupo alto estira la media hacia él. En este caso, tenemos que buscar una alternativa a la media aritmética, debemos de encontrar un buen indicador que nos indique con un número las máquinas demandadas por la mayoría en un pedido.
En este caso, vamos a utilizar la mediana, y lo que hace mediana es encontrar un número que deja 50% de los datos a un lado y otro 50% a otro lado. Podemos ilustrar la mediana en la siguiente imagen:
Mediana es como una balanza en equilibrio que deja el mismo número de datos a cada lado, y la magnitud de pocos datos altos no influye en la mediana. Para nuestro ejemplo, es un buen número para resumir el número de productos demandados en cada pedido.
library(kableExtra)
variables=c('n.prod= Número de productos enviados en el pedido',
'distance= Distancia entre proveedor y el cliente',
'deltime= Tiempo de entrega en días'
)
dt=data.frame(variables)
kable(dt) %>%
kable_styling(bootstrap_options = c("condensed","bordered"),
full_width = F, font_size = 14,position = "float_left")
| variables |
|---|
| n.prod= Número de productos enviados en el pedido |
| distance= Distancia entre proveedor y el cliente |
| deltime= Tiempo de entrega en días |
library(DT)
library(papeR)
delivery %>% papeR::summarise() %>%
datatable(options=list(scrollX = TRUE))
Como vemos en la tabla, n.prod es la variable que recoge los números de productos(máquinas) demandadas en cada pedido, y la media es 8.76 y la mediana 7 y en este caso, como ya hemos indicado las diferencias entre la media y la mediana, podemos concluir que el número de máquinas pedidas en cada pedido en la mayoría de casos es 7.
library(ggplot2)
library(plotly)
fig<-ggplot(delivery,aes(distance))+
geom_histogram(bins = 12,fill='#0B6889',color='#F37976')+
xlab('Distancia entre el proveedor y el cliente')+
ylab('total pedidos ')+
ylim(0,7)
p<-plotly::ggplotly(fig)
p
Observamos que la mayoría de los clientes suelen estar a una distancia de entre 0km y 500km, y hay un cliente que está muy alejado del resto y puede influir en la media. Por lo tanto, para responder a que distancia están los compradores, utilizaremos la mediana ,que es 330km, calculada arriba en la tabla.
Vemos que hay una observación que se aleja mucho de los demás, vamos a calcular la media aritmética eliminando dicha observación:
delivery1<-delivery[-which(delivery$distance==max(delivery$distance)),]
mean(delivery1$distance)
## [1] 365.5
Al eliminar la observación extrema, observamos que la media ahora tiene el valor de 365.5km, que es muy próximo a la mediana, que es 330km, pero no es un muy buen número para indicar la distancia a que estan los clientes , porque hay mucha variación. Por ejemplo, en el siguiente gráfico vemos que ambas, la zona verde y la roja, recogen 50% de los datos, pero la zona roja ocupa más espacio porque hay mucha variabilidad.
fig<-ggplot(delivery,aes(distance))+
geom_rect(aes(xmin=-70,xmax=330,ymin=0,ymax=Inf),alpha=0.02,fill='#15D798')+
geom_rect(aes(xmin=331,xmax=1500,ymin=0,ymax=Inf),alpha=0.02,fill='#FF3A3F')+
geom_histogram(bins = 12,fill='#0B6889',color='#F37976')+
annotate('text',x=10,y=8.5,label='50%',fontface = 'bold',size=6)+
annotate('text',x=1000,y=8.5,label='50%',fontface = 'bold',size=6)+
xlab('Distancia entre el proveedor y el cliente')+
ylab('total pedidos ')
fig
Entonces podemos decir que hay 2 tipos de clientes: unos que están a más de 330km y otros que están situados a menos de 330km del proveedor. Como Montgomery recogió los datos en EEUU podemos decir que reparte las máquinas por todo el país y tiene clientes que se sitúan en estados vecinos al estado del proveedor (<330km) y otros que se encuentran a estados lejanos(>330km);por ejemplo, entre San Francisco y Nueva York hay una distancia de 4300km ,y en nuestro dataset de 25 individuos, uno está situado a 1460km, pero, a lo mejor con más observaciones, llegaríamos a ver individuos situados a unas distancias mayores que 1460.
library(ggplot2)
library(plotly)
fig<-ggplot(delivery,aes(delTime))+
geom_histogram(bins = 10,fill='#FF5733',color='#56508C')+
xlab('Distancia entre el proveedor y el cliente')+
ylab('total pedidos ')
p<-plotly::ggplotly(fig)
p
Igual que en las variables anteriores vamos a elegir la mediana para decir cuantos días suele tardar en llegar un pedido, y la mediana es 18.11 días.
Observando los tres gráficos(histogramas), vemos que presentan los mismos patrones de que la mayoría de los datos están concentrados a la izquierda de los gráficos, presentan alguna relación?
library(plotly)
fig <- plot_ly(delivery, x = ~n.prod, y = ~delTime,size = ~delTime,
text = ~paste("Tiempo de entrega: ", delTime, 'días<br>Número de máquinas:',n.prod),
marker = list(color = '#09899E',
line = list(color = '#64BABF',
width = 1)))
fig <- fig %>% layout(title = '',
yaxis = list(zeroline = FALSE,title='Tiempo de entrega'),
xaxis = list(zeroline = FALSE,title='Número de productos'))
fig
Vemos en el gráfico ,donde en el eje horizontal tenemos el número de productos y en el eje vertical tenemos los tiempos de entrega, y vemos que, a medida que avanzamos en el eje horizontal, los puntos son cada vez más altos, es decir, aumentan en el eje vertical; por lo tanto, tienen una relación positiva.
Una relación entre dos elementos es positiva si al aumentar uno (mover uno) el otro también aumenta en la misma dirección, como lo vemos en la siguiente imagen y en nuestro caso las dos variables tienen esa relación positiva donde, al aumentar los número de productos, el tiempo de entrega también aumenta.
library(plotly)
fig <- plot_ly(delivery, x = ~distance, y = ~delTime,size = ~delTime,
text = ~paste("Tiempo de entrega: ", delTime, 'días<br>Distancia:',n.prod),
marker = list(color = '#CC79EB',
line = list(color = '#CC79EB',
width = 1)))
fig <- fig %>% layout(title = '',
yaxis = list(zeroline = FALSE,title='Tiempo de entrega'),
xaxis = list(zeroline = FALSE,title='Distancia entre el Proveedor y el Cliente'))
fig
Como en gráfico anterior, la relación es la misma: una relación positiva que indica que, a medida que aumenta la distancia, el tiempo de entrega lo hace también.
library(plotly)
fig <- plot_ly(delivery, x = ~distance, y = ~n.prod,size = ~n.prod,
text = ~paste("Productos: ", n.prod, 'días<br>Distancia:',distance),
marker = list(color = '#34A853',
line = list(color = '#34A853',
width = 1)))
fig <- fig %>% layout(title = '',
yaxis = list(zeroline = FALSE,title='Número de Productos'),
xaxis = list(zeroline = FALSE,title='Distancia entre el Proveedor y el Cliente'))
fig
Bueno, al mirar el gráfico da la sensación de que, a mayor distancia, el número de productos pedidos aumentan; sin embargo, vemos que, cuando el número de productos son mayores que 10, sólo tenemos 4 puntos, y, por lo tanto, no podemos ser guiados por sólo 4 puntos. Vamos a eliminar dichos 4 puntos y ver como cambia el gráfico.
mayor10<- which(delivery$n.prod > 10)
delivery2<-delivery[-mayor10,]
library(plotly)
fig <- plot_ly(delivery2, x = ~distance, y = ~n.prod,size = ~n.prod,
text = ~paste("Productos: ", n.prod, 'días<br>Distancia:',distance),
marker = list(color = '#34A853',
line = list(color = '#34A853',
width = 1)))
fig <- fig %>% layout(title = '',
yaxis = list(zeroline = FALSE,title='Número de Productos'),
xaxis = list(zeroline = FALSE,title='Distancia entre el Proveedor y el Cliente'))
fig
Volviendo a la pregunta ¿qué problemas parece tener la empresa para cumplir con las expectativas de sus clientes?
library(plotly)
fig <- plot_ly(delivery, x = ~distance, y = ~n.prod, z = ~delTime,
marker = list(color = ~delTime, colorscale = c('#FFE1A1', '#683531'), showscale = TRUE))
fig <- fig %>% add_markers()
fig <- fig %>% layout(scene = list(xaxis = list(title = 'distancia'),
yaxis = list(title = 'nº productos'),
zaxis = list(title = 'tiempo de entrega')),
annotations = list(
x = 1.13,
y = 1.05,
text = 'tiempo',
xref = 'paper',
yref = 'paper',
showarrow = FALSE
))
fig
library(threejs)
scatterplot3js(delivery$n.prod, delivery$distance, delivery$delTime, color=rainbow(length(delivery$delTime)))
Vemos los gráficos en 3D y vemos que hay dos grupos de datos: unos que piden 10 o más productos y se situan lejos del proveder y tiempo de entrega para ellos suele ser mayor, y otro grupo donde tenemos la mayoría de los datos y que en ese grupo también vemos mucha variabilidad.
<brProbelma principal de la empresa es la variablidad: dos individuos(25,5) que están situados a la misma distancia del proveedor, pero uno pide una cantidad mayor de productos y otro una menor. Entonces, estando a misma distancia, los tiempos de entrega varían mucho: a uno le llegará 3 días antes que al otro.
delivery3<-delivery[-mayor10,]
delivery3['individuos']<-as.numeric(rownames(delivery3))
delivery3['número_de_productos']<-delivery3$n.pro
fig <- plot_ly(delivery3, x = ~distance, y = ~delTime, type = 'scatter',
size = ~número_de_productos,color = ~número_de_productos,
text = ~individuos, textposition = 'top right',
textfont = list(color = '#000000', size = 16))
fig <- fig %>% layout(title = '',
xaxis = list(title = 'Distancia entre el proveedor y el cliente'
),
yaxis = list(title = 'Tiempo de entrega'
))
fig
Gráfico de los clientes que piden 10 o menos productos en el pedido demuestra la variablidad presente.
La empresa quiere mejorar su servicio a los clientes. En concreto, quiere dar a sus clientes una estimación/rango de estimación “fiable” con el número de días que tardará en recibir su pedido. Investiga este objetivo a través de las cuestiones a continuación y expresa tus conclusiones exclusivamente respondiendo a la pregunta ¿cómo vas a estimar el tiempo de entrega en el próximo pedido que reciba la empresa?
library(GGally)
ggpairs(delivery,columns = 3:1)
Como se observa en el gráfico tiempo de entregadeltime muestra correlaciones fuertes con el número de productos n.prod y la distancia distance, los coeficientes de correlación son positivos y cercanos al 1 : (0.892,0.965) lo que indican son fuertes relaciones positivas de dichas variables con el tiempo de entrega, por lo tanto, utilizaremos esas dos variables en el modelo.
Porque si sólo utilizamos n.prod estamos depreciando la información que aporta la distancia. Por ejemplo, hay varios individuos que piden exactamente 10 productos, pero lo que les diferencia es la distancia, y si no incluimos la distancia en nuestro modelo, entonces, a la hora de predecir, estaríamos dando la misma predicción del tiempo de entrega para todos aquellos que compran un número similar de productos, sin tener en cuenta dónde están situados.
En las ventas donde el número de productos pedidos es menor o igual que 10. En esa situación tenemos más datos para ajustar un buen modelo.
¿cómo vas a estimar el tiempo de entrega en el próximo pedido que reciba la empresa?
Vamos a estimar ajustando un modelo de regresión a los datos que utiliza la información tanto de la distancia que está el cliente como los productos que compra en su pedido, modelo de regresion consiste en ajustar una línea o un plano a los datos.
Modelo: \(\color{#0B6889}{tiempo\, de\, entrega=\beta_{0}+\beta_{1}*número\, de\, Productos+\beta_{2}*Distancia)}\)
options(rgl.useNULL=TRUE)
library(rgl)
knitr::knit_hooks$set(webgl = hook_webgl)
# 3D plot with the regression plane
scatter3d(x = delivery3$n.prod, y = delivery3$distance, z = delivery3$delTime)
You must enable Javascript to view this page properly.
Si la empresa recibiera hoy un pedido de 5 máquinas expendedoras, utilizando el guión de preguntas/tareas a continuación, expresa tus conclusiones respondiendo exclusivamente a la pregunta ¿cuánto tiempo tardaría en llegar el pedido de 5 máquinas?
modelosimple = lm(delTime ~ n.prod, data = delivery3)
summary(modelosimple)
##
## Call:
## lm(formula = delTime ~ n.prod, data = delivery3)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5.1729 -2.0298 -0.0298 0.8741 6.6722
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.5827 1.7217 3.823 0.00115 **
## n.prod 1.6490 0.2582 6.387 3.98e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.935 on 19 degrees of freedom
## Multiple R-squared: 0.6823, Adjusted R-squared: 0.6655
## F-statistic: 40.8 on 1 and 19 DF, p-value: 3.983e-06
predict.lm(modelosimple, newdata =data.frame(n.prod=5 ), interval = "confidence", level = 0.999997)
## fit lwr upr
## 1 14.82783 10.19279 19.46287
Un nivel de confianza de 99.9997% indica que si enviamos 1 millón de pedidos con 5 productos, sólo en 3 de dichos pedidos nuestro tiempo de entrega sería fuera del intervalo calculado, y, en términos de calidad, significa que siempre nuestro tiempo del entrega será en el intervalo proporcionado al cliente y es muy raro que el pedido sea entregado fuera de dicho intervalo..
library(kableExtra)
modelodis = lm(delTime ~ n.prod+distance, data = delivery)
summary(modelodis)
##
## Call:
## lm(formula = delTime ~ n.prod + distance, data = delivery)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5.7880 -0.6629 0.4364 1.1566 7.4197
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.341231 1.096730 2.135 0.044170 *
## n.prod 1.615907 0.170735 9.464 3.25e-09 ***
## distance 0.014385 0.003613 3.981 0.000631 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.259 on 22 degrees of freedom
## Multiple R-squared: 0.9596, Adjusted R-squared: 0.9559
## F-statistic: 261.2 on 2 and 22 DF, p-value: 4.687e-16
dis=data.frame(n.prod=c(5,5,5),distance=c(50,750,1150))
distancia=data.frame(predict(modelodis, newdata =dis, interval = "confidence", level = 0.999997))
distancia['distancia']=c(50,750,1150)
distancia['rango']=distancia$upr-distancia$lwr
kable(distancia) %>%
kable_styling(bootstrap_options = c("condensed","bordered"),
full_width = F, font_size = 14,position = "float_left")
| fit | lwr | upr | distancia | rango |
|---|---|---|---|---|
| 11.14001 | 4.485855 | 17.79416 | 50 | 13.30831 |
| 21.20939 | 9.338188 | 33.08059 | 750 | 23.74240 |
| 26.96332 | 6.528003 | 47.39863 | 1150 | 40.87063 |
Como vemos en la tabla, no podemos asegurar el mismo rango, porque la distancia tiene una relación positiva con los tiempos de entrega; entonces, a una mayor distancia, mayor es el tiempo de entrega.
modelosimple = lm(delTime ~ n.prod, data = delivery3)
x<-data.frame(predict( modelosimple,interval = "confidence", level = 0.999997))
x['rango']<-x$upr-x$lwr
kable(x) %>%
kable_styling(bootstrap_options = c("condensed","bordered"),
full_width = F, font_size = 14)
| fit | lwr | upr | rango | |
|---|---|---|---|---|
| 1 | 18.125873 | 13.730225 | 22.52152 | 8.791297 |
| 2 | 11.529794 | 4.722068 | 18.33752 | 13.615450 |
| 3 | 11.529794 | 4.722068 | 18.33752 | 13.615450 |
| 4 | 13.178814 | 7.604147 | 18.75348 | 11.149332 |
| 5 | 16.476853 | 12.285767 | 20.66794 | 8.382173 |
| 6 | 18.125873 | 13.730225 | 22.52152 | 8.791297 |
| 7 | 9.880774 | 1.677832 | 18.08372 | 16.405883 |
| 8 | 18.125873 | 13.730225 | 22.52152 | 8.791297 |
| 10 | 14.827834 | 10.192793 | 19.46287 | 9.270081 |
| 12 | 23.072933 | 15.415207 | 30.73066 | 15.315452 |
| 13 | 13.178814 | 7.604147 | 18.75348 | 11.149332 |
| 14 | 16.476853 | 12.285767 | 20.66794 | 8.382173 |
| 15 | 21.423913 | 15.110474 | 27.73735 | 12.626877 |
| 16 | 23.072933 | 15.415207 | 30.73066 | 15.315452 |
| 17 | 16.476853 | 12.285767 | 20.66794 | 8.382173 |
| 18 | 18.125873 | 13.730225 | 22.52152 | 8.791297 |
| 19 | 11.529794 | 4.722068 | 18.33752 | 13.615450 |
| 21 | 23.072933 | 15.415207 | 30.73066 | 15.315452 |
| 23 | 21.423913 | 15.110474 | 27.73735 | 12.626877 |
| 24 | 19.774893 | 14.602547 | 24.94724 | 10.344691 |
| 25 | 13.178814 | 7.604147 | 18.75348 | 11.149332 |
Si,lo podemos observar en la tabla y el modelo ajustado es sobre los clientes que compran 10 o menos productos.
¿cuánto tiempo tardaría en llegar el pedido de 5 máquinas?
Como vemos en la tabla de distancias que el tiempo de entrega para 5 productos depende del distancia entre el proveedor y el cliente.
Concluye, en base a todo el análisis que has realizado, respondiendo la pregunta: ¿cuáles son los problemas más relevantes que has detectado y que afectan a la satisfacción de los clientes y en consecuencia a la imagen y fiabilidad de la empresa?
Analizando los datos, el problema principal que surge es de variabilidad: la empresa no muestra consistencia en sus tiempos de entrega; la distancia y el número de productos comprados por el cliente hacen variar mucho sus tiempos de entrega, llegando a ser casi 80 días para los clientes que están lejos del proveedor. Por lo tanto, esto influye en la calidad, porque la empresa no es capaz de dar mismos intervalos de entrega a clientes que se sitúan a distancias similares.
Análisis muestra que hay dos grupos si miramos los productos comprados,unos que compran cantidades grandes y están situados lejos del proveedor y otros que compran poca cantidad y están cerca del proveedor pero esta relación entre la distancia y el número de productos comprados puede ser porque solo tenemos una pequeña muestra de 25 datos para dar más validez a ese argumento necesitamos más observaciones.
En base a los problemas que has detectado en tu análisis y a principios básicos de optimización, qué soluciones/medidas de mejora le propondrías a la empresa para aliviarlos o eliminarlos.
Soluciones: Primero, la empresa debería examinar su proceso, desde que el cliente realiza el pedido hasta que le llega dicho pedido, y encontrar elementos que hacen aumentar los tiempos de entrega.
Ahora bien, si después de examinarlo, encontramos que el problema es que el tiempo de preparación del pedido varía de un cliente a otro, entonces debe incluir más personal, investigar mejoras en la maquinaria o ver si un proceso lleva más tiempo que otros entonces romper dicho proceso en tareas simples, pero hacer que en la sede preparación del tiempo sea consistente.
Si probelma reside en la logística entonces debe investigar si necesita más camiones o abrir almacenes intermediarios donde guardar stock para las ventas que son a distancias largas.
Antes de implementar cualquier medida, primero el problema ha de ser medido e investigado; luego, comprobar con las medidas nuevas si dichas mejoran el proceso; y por último, controlar cómo va el nuevo proceso si se han implementado nuevas medidas.
Investiga librerías en R que te faciliten el análisis de la información y mejoren la forma de mostrar los resultados. Responde brevemente a la pregunta ¿qué librerías/funciones destacables has encontrado/utilizado, y cuáles son sus funcionalidades más relevantes?
ggplotly: para convertir gráficos ggplot en gráficos interactivos.
plotly: para crear gráficos interactivos como scatterplot en 3D.
paper: para crear una tabla de descriptivos de un dataframe.
DT: crea tablas dinámicas en Web.
Realizado por: Gur-E