Centro de Investigación y Docencia Económicas (CIDE) Región Centro

Manejo de Bases de Datos y Programación (R + STATA)
Actividad 3
Profesor: Dr. Héctor de la Torre Gutiérrez
Laboratorista: EME. Mario Arturo Aguilar López

Ejercicio 1

### Librerías
library(tidyverse)
### Lectura y limpieza
rend_raw <- readxl::read_xlsx(here::here("data/class/raw/Rendimiento.xlsx"))

# Se buscan NAs 
rend_raw %>%
  summarise(across(everything(), ~ sum(is.na(.x)))) %>%
  pivot_longer(cols = everything(),
               names_to = "Variable", 
               values_to = "Número de NAs")
Variable Número de NAs
No 0
Marca 0
MAKE MODEL 9
CLASS 2
ENGINE SIZE (L) 2
CYLINDERS 2
TRANSMISSION 2
FUEL TYPE 2
CONSUMPTION CITY (L/100 KM) 2
CONSUMPTION HIGHWAY (L/100 KM) 2
CONSUMPTION COMBINED (L/100 KM) 2
$ PER YEAR 10
CO2 EMISSIONS (g/km) 2
CO2 RATING 2

Limpieza

Reemplazo de NAs

# Se reemplazan los NAs por 0
rend_clean <- rend_raw %>%
  mutate(across(where(is.numeric), ~ replace_na(., 0))) %>%
  mutate(across(where(is.character), ~ replace_na(., "0")))

# Se verifica que no exista ningún NA 
rend_clean %>%
  summarise(across(everything(), ~ sum(is.na(.x)))) %>%
  pivot_longer(cols = everything(),
               names_to = "Variable", 
               values_to = "Número de NAs")
Variable Número de NAs
No 0
Marca 0
MAKE MODEL 0
CLASS 0
ENGINE SIZE (L) 0
CYLINDERS 0
TRANSMISSION 0
FUEL TYPE 0
CONSUMPTION CITY (L/100 KM) 0
CONSUMPTION HIGHWAY (L/100 KM) 0
CONSUMPTION COMBINED (L/100 KM) 0
$ PER YEAR 0
CO2 EMISSIONS (g/km) 0
CO2 RATING 0

Coerción de tipo de variable

Data <- readxl::read_excel(here::here("data/class/raw/Rendimiento.xlsx"), 
                   col_types = c("numeric", "text", "text", 
                                 "text", "numeric", "numeric", "text", 
                                 "text", "numeric", "numeric", "numeric", 
                                 "numeric", "numeric", "numeric"))
NAVals2 <- data.frame(apply(is.na(Data), 2, sum))
names(NAVals2) = c('ValFaltantes')
print(NAVals2)
##                                  ValFaltantes
## No                                          0
## Marca                                       0
## MAKE MODEL                                  9
## CLASS                                       2
## ENGINE SIZE (L)                             2
## CYLINDERS                                   2
## TRANSMISSION                                2
## FUEL TYPE                                   2
## CONSUMPTION  CITY (L/100 KM)                2
## CONSUMPTION  HIGHWAY (L/100 KM)             2
## CONSUMPTION  COMBINED (L/100 KM)            2
## $ PER YEAR                                 10
## CO2 EMISSIONS (g/km)                        2
## CO2 RATING                                  2

Como podemos ver el número de NAs no cambió.

Búsqueda y reemplazo de valores repetidos

# valores repetidos
rend_clean %>%
  select(-No) %>%
  duplicated() %>%
  sum(. == TRUE)
## [1] 0

No hay observaciones repetidas.

Auto que recomendaría a Fernanda Esquinca

# Se filtra por tamaño de motor y tipo de combustible
rend_fer <- rend_clean %>%
  filter(CLASS != "0",
         `ENGINE SIZE (L)` < 2 & 
           `FUEL TYPE` != "Z")

# Se calcula la media de consumo combinado
media_consumo <- mean(rend_fer$`CONSUMPTION  COMBINED (L/100 KM)`)

# Se hace el histograma antes de filtrar por la media
p1 <- rend_fer %>%
  ggplot() +
    geom_histogram(aes(`CONSUMPTION  COMBINED (L/100 KM)`), bins = 28, color = "orange", fill = "orange", alpha = 0.5) +
      geom_vline(aes(xintercept = media_consumo, color = "Media de\nconsumo\ncombinado"), linetype = "dashed", size = 1) +
  scale_x_continuous(breaks = scales::pretty_breaks(n = 5)) +
  scale_color_manual(name = "", values = c("Media de\nconsumo\ncombinado" = "black")) + 
  theme_minimal() +
  labs(title = "Consumo combinado de\nlos autos seleccionados",
       subtitle = glue::glue("n = {nrow(rend_fer)}"),
       x = "L/100 km",
       y = "Frecuencia")

# Se filtra por la media
rend_fer <- rend_fer %>%
  filter(`CONSUMPTION  COMBINED (L/100 KM)` <= media_consumo)

# Se hace el histograma después de filtrar por la media de consumo  
p2 <- rend_fer %>%
  ggplot() +
    geom_histogram(aes(`CONSUMPTION  COMBINED (L/100 KM)`), bins = 17, color = "blue", fill = "blue", alpha = 0.5) +
    geom_vline(aes(xintercept = as.numeric(rend_fer[which(rend_fer$`MAKE MODEL` == "CIVIC SEDAN"), "CONSUMPTION  COMBINED (L/100 KM)"]), color = "Civic\nSedan"), linetype = "dashed", size = 1) +
  scale_x_continuous(breaks = scales::pretty_breaks(n = 5)) +
  scale_color_manual(name = "", values = c("Civic\nSedan" = "green")) + 
  theme_minimal() +
  labs(title = "Consumo combinado de\nlos autos seleccionados\npor debajo de la media",
       subtitle = glue::glue("n = {nrow(rend_fer)}"),
       x = "L/100 km",
       y = "Frecuencia")

# Se grafica
ggpubr::ggarrange(p1, p2, ncol = 2)

No Marca MAKE MODEL CLASS ENGINE SIZE (L) CYLINDERS TRANSMISSION FUEL TYPE CONSUMPTION CITY (L/100 KM) CONSUMPTION HIGHWAY (L/100 KM) CONSUMPTION COMBINED (L/100 KM) $ PER YEAR CO2 EMISSIONS (g/km) CO2 RATING
102 CHEVROLET CRUZE C 1.4 4 AS6 X 7.8 5.6 6.8 1482 159 8
103 CHEVROLET CRUZE C 1.4 4 M6 X 8.2 5.8 7.1 1548 167 8
104 CHEVROLET CRUZE PREMIER C 1.4 4 AS6 X 7.8 5.9 6.9 1504 160 8
166 HONDA CIVIC COUPE C 1.5 4 AV X 7.5 5.6 6.7 1461 155 8
169 HONDA CIVIC SEDAN M 1.5 4 AV X 7.6 5.5 6.7 1461 157 8
172 HONDA CR-Z T 1.5 4 AV7 X 7.0 6.4 6.8 1482 157 8
173 HONDA CR-Z T 1.5 4 M6 X 7.9 6.5 7.3 1591 169 8
174 HONDA FIT WS 1.5 4 AV X 7.0 5.7 6.4 1395 150 8
175 HONDA FIT WS 1.5 4 AV7 X 7.3 6.1 6.8 1482 158 8
280 NISSAN SENTRA M 1.8 4 AV X 8.0 6.1 7.2 1570 167 8
282 NISSAN VERSA M 1.6 4 AV X 7.5 6.0 6.8 1482 161 8
317 SCION iM M 1.8 4 AV7 X 8.3 6.3 7.4 1613 173 8
341 TOYOTA COROLLA M 1.8 4 AV X 8.2 6.2 7.3 1591 171 8
342 TOYOTA COROLLA M 1.8 4 AV7 X 7.9 6.1 7.1 1548 166 8
343 TOYOTA COROLLA M 1.8 4 M6 X 8.4 6.4 7.5 1635 174 8
344 TOYOTA COROLLA LE ECO (1-mode) M 1.8 4 AV X 7.7 5.6 6.8 1482 160 8
345 TOYOTA COROLLA LE ECO (2-mode) M 1.8 4 AV X 7.7 6.0 6.9 1504 162 8

El auto que le recomendaría a mi amiga Fernanda sería el Honda Civic Sedan porque dado que reside en Rincón de Romos su uso del automóvil contemplaría recorridos en ciudad y en carretera, por esta razón, la variable de decisión fue el consumo combinado, ya que este auto cuenta con un consumo de 6.7 litros por cada 100 kilómetros, lo cual, para el tamaño del auto (Medio) es un consumo bastante bueno y se encuentra casi un litro por debajo de la media de todos los autos candidatos que le permitirá ahorrar una cantidad de dinero comparado con otros autos. Aunque el hecho de que sea soltera permitiría elegir un auto más pequeño, considero que un auto sedan como el Civic es una opción que no tendrá que reemplazar en mucho tiempo y que puede satisfacer necesidades futuras de espacio, por ejemplo, en el caso de que Fernanda forme una familia.

Para encontrar a los autos candidatos, lo primero fue filtrar por tamaño de motor que fuera menor a 2.0 litros, ya que Fernanda no necesitaría tanto poder para sus tareas diarias. En segundo lugar fue filtrar los autos que no necesitaran de combustible premium. Por último, de los autos restantes que eran 28, se contempló solo a aquellos que tuvieran un consumo combinado por debajo de la media de los 28 autos candidatos, la cual era de aproximadamente 7.5 litros por cads 100 kilómetros, lo que resultó en una muestra de 17 autos. Esta última comparación es la que se muestra en los histogramas.

Ejercicio 2

Lectura de los datos

Se utiliza la librería tabulizer para extraer la tabla del pdf “Actividad_cide”.

datos_act <- tabulizer::extract_tables(here::here("./Actividad_cide.pdf"), output = "data.frame")
datos_act_raw <- datos_act[[2]]

Estandarizar variable sexo

En este caso se decide estandarizar con “H” para hombre y “M” para mujer.

# Se obtienen los valores únicos de la codificación
unique(datos_act_raw$sexo)
## [1] "hombre"    "mujer"     "Femenino"  "masculino" "mascuino"  "Masculino"
## [7] "H"         "M"
# Se reemplazan por H para hombre y M para mujer
for(i in 1:nrow(datos_act_raw)){
  if(datos_act_raw$sexo[i] %in% c("hombre" , "masculino", "mascuino", "Masculino")){
    datos_act_raw$sexo[i] <- "H"
  }
  if(datos_act_raw$sexo[i] %in% c("mujer" , "Femenino")){
    datos_act_raw$sexo[i] <- "M"
  }
  else {
    next
  }
}
x
H
H
H
H
H
M
M
M
H
M
M
H
H
H
H
H
M
M
H
M
M
H
H
H
H
M
M
M
M
M
H
H
M
H
H
H
M
M
M
H

Estimación del ingreso

Segun los datos de la pagina https://mx.talent.com/salary los salarios para los empleos de la lista son los siguientes:

salarios = data.frame(
  "Enfermeria" = c(7000, 8250),
  "obrero" = c(5050, 4574),
  "mtro" = c(6500, 7072),
  "abogado" = c(9750, 7719),
  "politico" = c(7800, 9000)
)

Creamos la función.

sal = function(prof, gen){
  if(gen == 'H'){g = 2}
  if(gen == 'M'){g = 1}
  p = match(prof, names(salarios))
  return(salarios[g,p])
}

La aplicamos en los datos.

for (i in 1:length(datos_act_raw$empleo)) {
  datos_act_raw$ingreso[i] = sal(datos_act_raw$empleo[i], datos_act_raw$sexo[i])
}
obs encuestador sexo empleo ingreso edad altura peso
1 arturo H Enfermeria 8250 51 150.5 64.0
2 arturo H obrero 4574 33 155.7 62.0
3 arturo H mtro 7072 47 170.8 76.0
4 arturo H obrero 4574 38 166.0 67.0
5 arturo H abogado 7719 46 192.5 90.0
6 arturo M mtro 6500 47 171.7 80.0
7 arturo M obrero 5050 55 164.8 75.0
8 arturo M Enfermeria 7000 40 173.0 65.0
9 arturo H politico 9000 57 179.8 83.0
10 arturo M abogado 9750 NA 166.3 68.0
11 jessica M mtro 6500 56 168.5 62.0
12 jessica H obrero 4574 47 175.0 79.0
13 jessica H mtro 7072 36 155.8 65.0
14 jessica H mtro 7072 51 188.0 88.0
15 jessica H mtro 7072 41 188.3 74.0
16 jessica H abogado 7719 26 160.0 63.0
17 jessica M obrero 5050 52 179.4 86.0
18 jessica M abogado 9750 55 176.4 81.0
19 jessica H Enfermeria 8250 42 180.2 88.0
20 jessica M abogado 9750 40 188.3 95.0
21 susy M abogado 9750 52 165.2 68.0
22 susy H obrero 4574 62 166.0 76.0
23 susy H obrero 4574 49 166.0 70.0
24 susy H Enfermeria 8250 49 168.4 63.0
25 susy H obrero 4574 58 186.3 83.0
26 susy M obrero 5050 64 176.3 70.0
27 susy M obrero 5050 49 184.3 75.0
28 susy M obrero 5050 39 173.6 80.0
29 susy M politico 7800 70 166.0 66.0
30 susy M abogado 9750 44 181.3 76.0
31 pedro H obrero 4574 47 160.4 68.0
32 pedro H mtro 7072 40 183.3 76.0
33 pedro M Enfermeria 7000 34 164.5 NA
34 pedro H Enfermeria 8250 44 178.4 78.0
35 pedro H Enfermeria 8250 49 191.7 80.0
36 pedro H obrero 4574 33 168.0 73.0
37 pedro M obrero 5050 45 155.9 54.3
38 pedro M mtro 6500 49 188.0 NA
39 pedro M obrero 5050 46 186.0 88.0
40 pedro H obrero 4574 80 178.6 83.0

Estimación del peso

Se utiliza la siguiente fórmula para calcular el vector de estimaciones puntuales:

\[b = (X^TX)^{-1}X^Ty\]

datos_act_peso <- datos_act_raw %>%
  filter(!is.na(peso))

y_peso <- as.matrix(datos_act_peso$peso) # y
x_altura <- as.matrix(datos_act_peso["altura"]) # X
t_x_altura <- t(x_altura) # matriz traspuesta X^t

# vector de estimaciones puntuales
b <- (solve(t_x_altura%*%x_altura))%*%(t_x_altura%*%y_peso)

# Se estima el peso en las observaciones donde se tiene NA 
peso_na <- which(is.na(datos_act_raw$peso))
datos_act_raw[peso_na, ]
##    obs encuestador sexo     empleo ingreso edad altura peso
## 33  33       pedro    M Enfermeria    7000   34  164.5   NA
## 38  38       pedro    M       mtro    6500   49  188.0   NA
for(i in which(is.na(datos_act_raw$peso))){
  datos_act_raw$peso[i] <- datos_act_raw$altura[i]*b
}
Peso estimado de las observaciones
obs encuestador sexo empleo ingreso edad altura peso
33 33 pedro M Enfermeria 7000 34 164.5 71.05027
38 38 pedro M mtro 6500 49 188.0 81.20031

Las observaciones 33 y 38 fueron a las que se les estimó el peso. Con un estimador \(b\) de 0.432, se obtuvo un peso estimado de 71.05 y 81.2 kilos respectivamente.

La recta de regresión sería:

\[\hat{peso} = 0.432\ altura\]

Ejercicio 3

Sea \(X\) una variable aleatoria Binomial(\(n\), \(p\)) y \(Y\) una variable binomial condicionada en \(X\); esto es, (\(Y|X=x\)) tiene una distribución binomial (\(X + 1\), \(q\)).

a. Hacer la función masa de probabilidad conjunto \(X\), \(Y\) cuando \(n = 5\), \(p = 0.5\) y \(q = 0.5\).

Considerando que una probabilidad condicional de \(Y\) dado \(X = x\) es:

\[f_{Y|X}(y|x) = \frac{f(x,y)}{f_X(x)}\] donde \(f(x,y)\) es la función de probabilidad conjunta y \(f_X(x)\) es la función de probabilidad marginal de \(X\).

Se parte de la función marginal y condicional para encontrar la función de probabilidad conjunta:

\[f(x,y) = f_X(x)f_{Y|X}(y|x)\]

Se crea la función marginal y condicional con los valores de los parámetros dados (\(n = 5\), \(p = 0.5\) y \(q = 0.5\)):

# función de probabilidad conjunta de X y Y
f_x_y <- function(x, n = 5, p = 0.5){
  
# Parámetros de Y|X
q <- 1 - p
n_y <- x + 1

# Marginal de X
f_x <- choose(n, x)*(p^x)*((1-p)^(n-x))
y <- c(0:n_y)

  # Bucle for para calcular los valores de y 
  f_y_cond_x <- c()
  for(i in y){
    f_y_cond_x <- c(f_y_cond_x, choose(n_y, i)*(q^n_y)*((1-q)^(n_y-i)))
  }

# Producto de la marginal de X y la condicional de Y|X
f_x * f_y_cond_x
}

Se crea la tabla con la probabilidad conjunta:

x_vals <- c(0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5)
y_vals <- c(0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6)
conjunta_x_y <- unlist(sapply(0:5, f_x_y))

tabla_conjunta_x_y <- data.frame(x = x_vals,
                           y = y_vals,
                           "P(X)*P(Y|X)" = conjunta_x_y)
x y P.X..P.Y.X.
0 0 0.0078125
0 1 0.0156250
1 0 0.0097656
1 1 0.0390625
1 2 0.0390625
2 0 0.0048828
2 1 0.0292969
2 2 0.0585938
2 3 0.0390625
3 0 0.0012207
3 1 0.0097656
3 2 0.0292969
3 3 0.0390625
3 4 0.0195312
4 0 0.0001526
4 1 0.0015259
4 2 0.0061035
4 3 0.0122070
4 4 0.0122070
4 5 0.0048828
5 0 0.0000076
5 1 0.0000916
5 2 0.0004578
5 3 0.0012207
5 4 0.0018311
5 5 0.0014648
5 6 0.0004883

b. Proporcione la función masa de probabilidad para \(Y\).

Ahora en el caso de una condicional de \(X\) dado \(Y\):

\[f_{X|Y}(x|y) = \frac{f(x,y)}{f_Y(y)}\]

Se puede obtener la marginal de \(Y\):

\[f_Y(y) = \frac{f(x,y)}{f_{X|Y}(x|y)}\]