library(knitr)
library(rmdformats)

## Global options
options(max.print = "75")
opts_chunk$set(echo = TRUE,
                 cache = FALSE,
               prompt = FALSE,
               tidy = FALSE,
               comment = NA,
               message = TRUE,
               warning = FALSE)
opts_knit$set(width = 95)

1 Búsqueda Selección y Evaluación de Proveedores

1.1 Caso de estudios “Selección de un Proveedor de la Industria Siderurgica”

Metodología Utilizada : Medición de la Performance Logística

1.1.1 Análisis Exploratorio

Una de las cosas interesantes de uso del la Simulación de Sistemas de Manu- factura es la posibilidad de hacer Inteligencia de Negocios (BI por sus siglas en ingles – Business Intelligence) por la enorme cantidad de datos que nos genera. Este campo de la BI, requiere un dominio de técnicas como Machine Learning, Identificación de Patrones, operación de BigData o Minerı́a de Datos que en general dominan los expertos en informática, pero que cada dı́a son más acce- sibles a otros profesionales. Si bien serı́a posible poder hacer esto en excel, las limitaciones que tiene la hoja de cálculo nos imedirı́an trabajar con el volumen de datos que la simulación aportarı́a. Se quiere hacer notar que si bien no es imposible hacer el trabajo con hoja de cáculo, serı́a mejor utilizarla para apren- der y resignarse a trabajar con pocos datos. En esta serie de ejercicios, además de familiarizarnos con el lenguaje R-Cran que SI puede operar en entornos de BIGDATA, trataremos de ver como podemos valernos de las bondades del en- torno de trabajo y aprender de un sólo paso con las herramientas que se utilizan en la vida real. Hasta ahora tenemos claro temas referidos a los conceptos de Simulación, Modelo, Inferencia , y hemos insinuado algo sobre las estructuras y métodos de ajustes del modelo o del concepto de ingenierı́a inversa. Utilizaremos unas bases de datos ficticias (cualquier semejanza con la reali- dad es pura coincidencia). En ella se ha realizado un estudio sobre varias empresas que son contratistas o proveedores de servicios de alto valor agregado de grandes compañı́as manu- factureras. Se ha indagado el desempeño de unos 150 contratistas según cuadro dimensiones o indicadores. Comenzaremos estos ejercicios cargando los datos externos, que incluso po- drı́an venir de una hoja de cálculo.

Carga de datos desde archivos externos Si bien serı́a posible cargar datos a mano en R-CRAN, no serı́a práctico hacer lo ası́. Todos los datos que se utilizan en este entorno de trabajo se manejan

internamente como matrices. Estas matrices de datos (semejantes a bases de datos) se llaman data-frames. Un data frame podrı́a ser una matriz de una fila por una columna ası́ por ejemplo

X <-200 # Le asigna a X el valor 200 (usando la flecha a izquierda)
Y= 20 # Le asiga a Y el valor 20
Z <- 33 # 
Y= X+Z # Suma X + Y y muestra el resultado 220

Tanto X,Y y Z aparecen como variables, pero R-CRAN los trata como ma- trices de 1x1. Intente carga dos dataframes a y b con valores numéricos y realizamos la suma de ambos como se muestra en el código. Esto nos permitirı́a usar R-CRAN como si se tratase de una calculadora.

¿Desde dónde podemos cargar datos? Uno de los requisitos para poder cargar datos es que sepamos en que carpeta estamos trabajando. En este ejercicio veremos como hacer para saber donde estamos parados.

getwd()
[1] "/media/rpalma/OS/AAA_Datos/2022/Posgrado/UCB/Apunte/Seleccion_proveedores"

Se puede cambiar la carpeta de trabajo con

  setwd("C:/Apuntes")

Puedes cambiar tu carpeta (directorio) de trabajo con el comando setwd() Debes poner entre comillas lo que va dentro del paréntesis Prepare un archivo en excel y guardelo con formato csv ”comma separated values” para capturarlo desde R-CRAN. Asegúrate de usar punto ”.” para indicar fracciones y coma para separar los campos o columnas de la tabla.

  Tarea: Crea una carpeta para tus datasets y descarga la base de proveedores desde https://themys.sid.uncu.edu.ar/r-cran/

Link de descarga

Ejemplos

Con los siguientes comando importaremos una planilla generada con una hoja de cálculo que contiene las 150 respuestas de las encuestas que se realizaron

# Si aún no has cargado una biblioteca recuerda ejecutar
# install.packages("readr") o utiliza el menú de R-Studio
library(readr)
BSC_proveedores <- read_csv("~/BSC_proveedores.csv")
New names:
Rows: 150 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Empresa
dbl (5): ...1, Tecnologia, Normas, Capital, Equipo

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
* `` -> `...1`
BSC_proveedores [c(1:5 ,70:73, 126:129) , ]
…1 Tecnologia Normas Capital Equipo Empresa
1 5.1 3.5 1.4 0.2 Tenaris
2 4.9 3.0 1.4 0.2 Tenaris
3 4.7 3.2 1.3 0.2 Tenaris
4 4.6 3.1 1.5 0.2 Tenaris
5 5.0 3.6 1.4 0.2 Tenaris
70 5.6 2.5 3.9 1.1 Tenova
71 5.9 3.2 4.8 1.8 Tenova
72 6.1 2.8 4.0 1.3 Tenova
73 6.3 2.5 4.9 1.5 Tenova
126 7.2 3.2 6.0 1.8 Ternium
127 6.2 2.8 4.8 1.8 Ternium
128 6.1 3.0 4.9 1.8 Ternium
129 6.4 2.8 5.6 2.1 Ternium

La biblioteca readr permite importar datos de excel en r-cran Podemos ver el contenido del dataframe BSC Proveedores que se llama igual que el archivo de texto separado por comas. Para ello ejecutamos el siguiente comando.

1.1.2 Analizando el contenido de un data.frame

Si quisiésemos ver el desempeño respecto a la variable TECNNOLOGIA tendríamos que interponer entre el nombre del dataset el signo pesos y luego el nombre de la columna

1.1.3 Contenido de Columnas

BSC_proveedores$Tecnologia
 [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7
[20] 5.1 5.4 5.1 4.6 5.1 4.8 5.0 5.0 5.2 5.2 4.7 4.8 5.4 5.2 5.5 4.9 5.0 5.5 4.9
[39] 4.4 5.1 5.0 4.5 4.4 5.0 5.1 4.8 5.1 4.6 5.3 5.0 7.0 6.4 6.9 5.5 6.5 5.7 6.3
[58] 4.9 6.6 5.2 5.0 5.9 6.0 6.1 5.6 6.7 5.6 5.8 6.2 5.6 5.9 6.1 6.3 6.1 6.4
 [ reached getOption("max.print") -- omitted 75 entries ]

Repita todo el proceso con el resto de la dimensiones NORMA, CAPITAL, EQUIPO, EMPRESA.

1.1.4 Análisis de Histograma

Veremos como se comportan las muestras (contratistar) utilizando el histograma

hist(BSC_proveedores$Tecnologia)

El gráfico nos muestra que hay dos grupos de contratistas (casi 29 ocurrencias en cada uno) con un desempeño de 6 en la variable TECNOLOGÍA . La escala original era de 1 a 10. Utilizaremos el comando par() que permite dividir el área de ploteo en una matriz especificada por el comando Numero de Columna (nmfrow) Haga las interpretaciones de estos gráficos.

par(mfrow=c(2,2))
hist(BSC_proveedores$Tecnologia)
hist(BSC_proveedores$Normas)
hist(BSC_proveedores$Capital)
hist(BSC_proveedores$Equipo)

1.1.5 Gráficos de Densidad

Algunas personas prefieren utilizar la envolvente del histograma que es el gráfico de densidad

par(mfrow=c(1,1))
plot(density(BSC_proveedores$Equipo))

Gráficos 4x4 de Densidad

par(mfrow=c(2,2))
plot(density(BSC_proveedores$Tecnologia))
plot(density(BSC_proveedores$Normas))
plot(density(BSC_proveedores$Capital))
plot(density(BSC_proveedores$Equipo))

1.1.6 Análisis Mutivariado

Gráficas Ralas

library(car)
Loading required package: carData
BSC_Rawdata <- BSC_proveedores[ ,c(2,3,4,5)]
BSC_Rawdata
Tecnologia Normas Capital Equipo
5.1 3.5 1.4 0.2
4.9 3.0 1.4 0.2
4.7 3.2 1.3 0.2
4.6 3.1 1.5 0.2
5.0 3.6 1.4 0.2
5.4 3.9 1.7 0.4
4.6 3.4 1.4 0.3
5.0 3.4 1.5 0.2
4.4 2.9 1.4 0.2
4.9 3.1 1.5 0.1
5.4 3.7 1.5 0.2
4.8 3.4 1.6 0.2
4.8 3.0 1.4 0.1
4.3 3.0 1.1 0.1
5.8 4.0 1.2 0.2
5.7 4.4 1.5 0.4
5.4 3.9 1.3 0.4
5.1 3.5 1.4 0.3
5.7 3.8 1.7 0.3
5.1 3.8 1.5 0.3
5.4 3.4 1.7 0.2
5.1 3.7 1.5 0.4
4.6 3.6 1.0 0.2
5.1 3.3 1.7 0.5
4.8 3.4 1.9 0.2
5.0 3.0 1.6 0.2
5.0 3.4 1.6 0.4
5.2 3.5 1.5 0.2
5.2 3.4 1.4 0.2
4.7 3.2 1.6 0.2
4.8 3.1 1.6 0.2
5.4 3.4 1.5 0.4
5.2 4.1 1.5 0.1
5.5 4.2 1.4 0.2
4.9 3.1 1.5 0.2
5.0 3.2 1.2 0.2
5.5 3.5 1.3 0.2
4.9 3.6 1.4 0.1
4.4 3.0 1.3 0.2
5.1 3.4 1.5 0.2
5.0 3.5 1.3 0.3
4.5 2.3 1.3 0.3
4.4 3.2 1.3 0.2
5.0 3.5 1.6 0.6
5.1 3.8 1.9 0.4
4.8 3.0 1.4 0.3
5.1 3.8 1.6 0.2
4.6 3.2 1.4 0.2
5.3 3.7 1.5 0.2
5.0 3.3 1.4 0.2
7.0 3.2 4.7 1.4
6.4 3.2 4.5 1.5
6.9 3.1 4.9 1.5
5.5 2.3 4.0 1.3
6.5 2.8 4.6 1.5
5.7 2.8 4.5 1.3
6.3 3.3 4.7 1.6
4.9 2.4 3.3 1.0
6.6 2.9 4.6 1.3
5.2 2.7 3.9 1.4
5.0 2.0 3.5 1.0
5.9 3.0 4.2 1.5
6.0 2.2 4.0 1.0
6.1 2.9 4.7 1.4
5.6 2.9 3.6 1.3
6.7 3.1 4.4 1.4
5.6 3.0 4.5 1.5
5.8 2.7 4.1 1.0
6.2 2.2 4.5 1.5
5.6 2.5 3.9 1.1
5.9 3.2 4.8 1.8
6.1 2.8 4.0 1.3
6.3 2.5 4.9 1.5
6.1 2.8 4.7 1.2
6.4 2.9 4.3 1.3
6.6 3.0 4.4 1.4
6.8 2.8 4.8 1.4
6.7 3.0 5.0 1.7
6.0 2.9 4.5 1.5
5.7 2.6 3.5 1.0
5.5 2.4 3.8 1.1
5.5 2.4 3.7 1.0
5.8 2.7 3.9 1.2
6.0 2.7 5.1 1.6
5.4 3.0 4.5 1.5
6.0 3.4 4.5 1.6
6.7 3.1 4.7 1.5
6.3 2.3 4.4 1.3
5.6 3.0 4.1 1.3
5.5 2.5 4.0 1.3
5.5 2.6 4.4 1.2
6.1 3.0 4.6 1.4
5.8 2.6 4.0 1.2
5.0 2.3 3.3 1.0
5.6 2.7 4.2 1.3
5.7 3.0 4.2 1.2
5.7 2.9 4.2 1.3
6.2 2.9 4.3 1.3
5.1 2.5 3.0 1.1
5.7 2.8 4.1 1.3
6.3 3.3 6.0 2.5
5.8 2.7 5.1 1.9
7.1 3.0 5.9 2.1
6.3 2.9 5.6 1.8
6.5 3.0 5.8 2.2
7.6 3.0 6.6 2.1
4.9 2.5 4.5 1.7
7.3 2.9 6.3 1.8
6.7 2.5 5.8 1.8
7.2 3.6 6.1 2.5
6.5 3.2 5.1 2.0
6.4 2.7 5.3 1.9
6.8 3.0 5.5 2.1
5.7 2.5 5.0 2.0
5.8 2.8 5.1 2.4
6.4 3.2 5.3 2.3
6.5 3.0 5.5 1.8
7.7 3.8 6.7 2.2
7.7 2.6 6.9 2.3
6.0 2.2 5.0 1.5
6.9 3.2 5.7 2.3
5.6 2.8 4.9 2.0
7.7 2.8 6.7 2.0
6.3 2.7 4.9 1.8
6.7 3.3 5.7 2.1
7.2 3.2 6.0 1.8
6.2 2.8 4.8 1.8
6.1 3.0 4.9 1.8
6.4 2.8 5.6 2.1
7.2 3.0 5.8 1.6
7.4 2.8 6.1 1.9
7.9 3.8 6.4 2.0
6.4 2.8 5.6 2.2
6.3 2.8 5.1 1.5
6.1 2.6 5.6 1.4
7.7 3.0 6.1 2.3
6.3 3.4 5.6 2.4
6.4 3.1 5.5 1.8
6.0 3.0 4.8 1.8
6.9 3.1 5.4 2.1
6.7 3.1 5.6 2.4
6.9 3.1 5.1 2.3
5.8 2.7 5.1 1.9
6.8 3.2 5.9 2.3
6.7 3.3 5.7 2.5
6.7 3.0 5.2 2.3
6.3 2.5 5.0 1.9
6.5 3.0 5.2 2.0
6.2 3.4 5.4 2.3
5.9 3.0 5.1 1.8
scatterplotMatrix(BSC_Rawdata)

Gráficas de matriz de co-varianza

Circulos

library(corrplot)
corrplot 0.92 loaded
M <- cor(BSC_Rawdata)
corrplot(M, method="circle")

Cuadrados

library(corrplot)
M <- cor(BSC_Rawdata)
corrplot(M, method="square")

    Tarea: probar los gráficos "circle", "square", "ellipse", "number", "shade", "color", "pie" 

1.1.7 Clusterizacion básica

Transformaremos la columna Empresas en una variable categórica de tres niveles

BSC_proveedores[ ,7] <- factor(BSC_proveedores$Empresa) 
pairs(BSC_proveedores[2:5], main="Proveedores", pch=21, bg = c("red", "green3", "blue")[unclass(BSC_proveedores$...7)] )

2 Uso de neural net para clasificar

Una alternativa interesante respecto del método de selección de proveedores es la utilización del método de redes neuronales.

Utilizaremos el mismo dataset anterior y propondremos el entrenamiento de una red neuromal simple, pero que en lugar de una sóla neurona en la que leemos un valor nos entregue como salida 3 neuronas que corresponden al provvedor más indicado para una empresa nueva que quiere instalarse en este mercado.

Si bien ya hemos invocado las bibliotecas neural net, volveremos a hacerlo en este apartado para que puedas tener el código completo sin necesidad de copiar los pasos del ejercicio anterior.

library(neuralnet)
library(caret)
Loading required package: ggplot2
Loading required package: lattice

Verificaremos el dataset BSC_proveedores

library(readr)
BSC_proveedores <- read_csv("~/BSC_proveedores.csv")
New names:
Rows: 150 Columns: 6
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Empresa
dbl (5): ...1, Tecnologia, Normas, Capital, Equipo

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
* `` -> `...1`
str(BSC_proveedores)
spec_tbl_df [150 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ...1      : num [1:150] 1 2 3 4 5 6 7 8 9 10 ...
 $ Tecnologia: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Normas    : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Capital   : num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Equipo    : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Empresa   : chr [1:150] "Tenaris" "Tenaris" "Tenaris" "Tenaris" ...
 - attr(*, "spec")=
  .. cols(
  ..   ...1 = col_double(),
  ..   Tecnologia = col_double(),
  ..   Normas = col_double(),
  ..   Capital = col_double(),
  ..   Equipo = col_double(),
  ..   Empresa = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

Eliminaremos la primer columna que no aporta información

BSC_proveedores <- BSC_proveedores[ ,-1]

Para poder emplear la técnica de tres neuronas de salida es necesario que cambiemos la clase “Character” de la columna Empresa a un tipo nuevo llamado Factor. Esto implica conver tir texto en categorías que es un tipo especial de clase.

BSC_proveedores$Empresa <- as.factor(BSC_proveedores$Empresa)
str(BSC_proveedores)
tbl_df [150 × 5] (S3: tbl_df/tbl/data.frame)
 $ Tecnologia: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Normas    : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Capital   : num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Equipo    : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Empresa   : Factor w/ 3 levels "Tenaris","Tenova",..: 1 1 1 1 1 1 1 1 1 1 ...
class(BSC_proveedores$Empresa)
[1] "factor"
levels(BSC_proveedores$Empresa)
[1] "Tenaris" "Tenova"  "Ternium"

2.1 Particionado del dataset para entrenamiento y prueba

set.seed(123)
 
indexes=createDataPartition(BSC_proveedores$Empresa, p=.85, list = F) #Generamos los índices con un tipo de muestreo que usa la biblioteca CARET
train = BSC_proveedores[indexes, ] # Tenemos el set en entrenamiento
test = BSC_proveedores[-indexes, ] # Tenemos el set de pruebas

2.2 Construcción del modelo (o fórmula) de la red neuronal

Nuevamente es sorprendente que en una síntaxis tan compacta pueda expresarse con tanta riqueza el modelo que queremos entrenar. Esta es, tal vez, la mayor ventaja de R-Cran frente a otros lenguajes.

nnet=neuralnet(Empresa~., train, hidden = c(4,3), linear.output = FALSE)
plot(nnet,rep="best")

2.3 Predicción de resultados

ypred = neuralnet::compute(nnet, test)
 
yhat = ypred$net.result
print(round(yhat,digits = 0))
      [,1] [,2] [,3]
 [1,]    1    0    0
 [2,]    1    0    0
 [3,]    1    0    0
 [4,]    1    0    0
 [5,]    1    0    0
 [6,]    1    0    0
 [7,]    1    0    0
 [8,]    0    1    0
 [9,]    0    1    0
[10,]    0    1    0
[11,]    0    1    0
[12,]    0    1    0
[13,]    0    1    0
[14,]    0    1    0
[15,]    0    0    1
[16,]    0    0    1
[17,]    0    0    1
[18,]    0    0    1
[19,]    0    0    1
[20,]    0    0    1
[21,]    0    0    1

Predicción para una sola empresa nueva

Empresa nueva se quiere instalar en la región y quiere saber que proveedor debería selecciona si sus datos son los siguientes:

  • Tecnología 5
  • Normas 2.5
  • Capital 3
  • Equipo 1
test2 <- test[1, ]
test2[1,1] <- 5
test2[1,2] <- 2.5
test2[1,3] <- 3
test2[1,4] <- 1
test2
Tecnologia Normas Capital Equipo Empresa
5 2.5 3 1 Tenaris
ypred = neuralnet::compute(nnet, test2)
round(ypred$net.result,digits=0)
     [,1] [,2] [,3]
[1,]    1    0    0
levels(BSC_proveedores$Empresa)
[1] "Tenaris" "Tenova"  "Ternium"

3 Uso de árboles

El método de los árboles cuya expresión máxima es el random-forest es uno de los más utilizados para clasificar datasets.

Utilizaremos las siguientes bibliotecas

library(scatterPlotMatrix)
library(party)
Loading required package: grid
Loading required package: mvtnorm
Loading required package: modeltools
Loading required package: stats4

Attaching package: 'modeltools'
The following object is masked from 'package:car':

    Predict
Loading required package: strucchange
Loading required package: zoo

Attaching package: 'zoo'
The following objects are masked from 'package:base':

    as.Date, as.Date.numeric
Loading required package: sandwich
scatterPlotMatrix(BSC_proveedores)

Al igual que en el caso anterior utilizaremos una tecnica de remuestreo para poder utilizar una partes de los datos para entrenar el árbol y la segunda para verifiacar la calidad del modelo

ind <- sample(2, nrow(BSC_proveedores), replace=TRUE, prob=c(0.7, 0.3))  
# toma una muestra u crea la tabla de índices  
ind  
 [1] 1 2 1 1 1 1 1 1 2 1 1 1 2 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 1 1 2
[39] 2 1 2 2 1 1 1 1 1 1 1 1 2 1 1 2 2 1 1 2 2 1 1 2 1 1 2 1 1 2 1 1 2 2 1 1 1
 [ reached getOption("max.print") -- omitted 75 entries ]
# nos imprime la muestra tomada (sólo sus índices.

Creo el árbol de selección de alternativas

trainData <- BSC_proveedores [ind==1,]    
# genero un set de entrenamiento 
testData <- BSC_proveedores [ind==2,]    
# genero un expresión matemáica de la formula
# en este caso no uso el punto, sino los nombres de las columnas del vectos
myFormula <- Empresa ~ Tecnologia + Capital + Normas + Equipo 
transit_ctree <- ctree(myFormula, data=trainData)    
# creo el motor de entrenamiento
# Verifico las prediciones usando el modelo transit_ctree y los datos 
# de entrenamiento
table(predict(transit_ctree), trainData$Empresa) 
         
          Tenaris Tenova Ternium
  Tenaris      36      0       0
  Tenova        0     35       3
  Ternium       0      0      30
print(transit_ctree) 

     Conditional inference tree with 4 terminal nodes

Response:  Empresa 
Inputs:  Tecnologia, Capital, Normas, Equipo 
Number of observations:  104 

1) Capital <= 1.9; criterion = 1, statistic = 97.353
  2)*  weights = 36 
1) Capital > 1.9
  3) Equipo <= 1.6; criterion = 1, statistic = 47.405
    4) Capital <= 4.7; criterion = 0.999, statistic = 13.344
      5)*  weights = 31 
    4) Capital > 4.7
      6)*  weights = 7 
  3) Equipo > 1.6
    7)*  weights = 30 
# Vemos el detalle de la matriz de confusión

Predicciones con el set de verificación

table(predict(transit_ctree), trainData$Empresa)
         
          Tenaris Tenova Ternium
  Tenaris      36      0       0
  Tenova        0     35       3
  Ternium       0      0      30

Visualizaremos el algoritmo (árbol) que la biblioteca ha creado para nosotros basado en los datos de entrenamiento y aplicado al dataset de verificación

plot(transit_ctree, las=2)