Punto 1 (1pt)

• Filtre para la base de datos iris (en inglés) los datos que tienen un ancho de sépalo mayor 4 o un ancho de sépalo inferior a 2,9.

library(datos)
attach(iris) 
library(dplyr)
DatosSepal <- iris %>%
  filter(Sepal.Width > 4 | Sepal.Width < 2.9)
head(DatosSepal)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 1          5.7         4.4          1.5         0.4     setosa
## 2          5.2         4.1          1.5         0.1     setosa
## 3          5.5         4.2          1.4         0.2     setosa
## 4          4.5         2.3          1.3         0.3     setosa
## 5          5.5         2.3          4.0         1.3 versicolor
## 6          6.5         2.8          4.6         1.5 versicolor

• Filtre para la base de datos iris (en inglés) los datos que son versicolor.

DatosVersi <- iris %>%
  filter(Species=="versicolor")
head(DatosVersi)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 1          7.0         3.2          4.7         1.4 versicolor
## 2          6.4         3.2          4.5         1.5 versicolor
## 3          6.9         3.1          4.9         1.5 versicolor
## 4          5.5         2.3          4.0         1.3 versicolor
## 5          6.5         2.8          4.6         1.5 versicolor
## 6          5.7         2.8          4.5         1.3 versicolor

• Agrupe la base de datos por species, calcule la media para 2 variables de su elección, el tamaño y la desviación para 1 de ellas. ¿Qué puede analizar de los datos?

DatosAgrup <- iris %>%
  group_by(Species) %>%
  summarise(
    Media_Sepal_Length = mean(Sepal.Length, na.rm = TRUE),
    Media_Petal_Length = mean(Petal.Length, na.rm = TRUE),
    Tamaño = n(),
    Desviación_Sepal_len = sd(Sepal.Length, na.rm = TRUE)
  )

DatosAgrup
## # A tibble: 3 × 5
##   Species    Media_Sepal_Length Media_Petal_Length Tamaño Desviación_Sepal_len
##   <fct>                   <dbl>              <dbl>  <int>                <dbl>
## 1 setosa                   5.01               1.46     50                0.352
## 2 versicolor               5.94               4.26     50                0.516
## 3 virginica                6.59               5.55     50                0.636

• Realice un intervalo de confianza del 98% para una de las variables seleccionadas en el item anterior.

t.test(iris$Sepal.Length, conf.level = 0.98)
## 
##  One Sample t-test
## 
## data:  iris$Sepal.Length
## t = 86.425, df = 149, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 98 percent confidence interval:
##  5.684336 6.002330
## sample estimates:
## mean of x 
##  5.843333

Esto significa que, con un 98% de confianza, el valor promedio verdadero de Sepal.Length en la población está entre 5.684 y 6.002.

Punto 2 (1pt)

• De las bases de datos Cartera, Oficinas, Cuenta de Ahorro, Cuenta corriente e Individuos. Unir en un data frame, los individuos y cartera por la variable LLAVE, diga cuántos faltantes hay, en que variables se encuentran y que porcentaje son.

Cartera<-read.csv(file="Cartera.csv",sep=";",dec=",")
Individuos<-read.csv(file="Individuos.csv",sep=";",dec=",")
CarteIndi<-merge(x=Individuos,y=Cartera, by.x="llave",
            by.y="Llave",all.x=T)

x_nulos <- colSums(is.na(CarteIndi)) 
#Registros nulos 
x_nulos
##     llave      Edad    GENERO   Oficina EDUCACION    estado     SALDO SALDO_VCD 
##         0         0         0         0         0         2         2         2 
## TIPO_PAGO 
##         2
xporce_nulos <- colMeans(is.na(CarteIndi)) * 100  
#Porcentaje nulos
xporce_nulos
##     llave      Edad    GENERO   Oficina EDUCACION    estado     SALDO SALDO_VCD 
##  0.000000  0.000000  0.000000  0.000000  0.000000  1.219512  1.219512  1.219512 
## TIPO_PAGO 
##  1.219512

• Para la base de datos encontrada anteriormente filtre por las que el TIPO_PAGO mensual y muestre las últimas 10 observaciones.

observacione_last_10 <- CarteIndi %>%
  filter(TIPO_PAGO == "MENSUAL") %>%
tail(10)

observacione_last_10
##    llave Edad    GENERO Oficina     EDUCACION   estado     SALDO SALDO_VCD
## 76  1877   44  FEMENINO    5000      PRIMARIA   ACTIVO 189730470  13247854
## 77  1877   44  FEMENINO    5000      PRIMARIA   ACTIVO   7018485         0
## 78  1888   41  FEMENINO    3000     BACHILLER INACTIVO  72503133   1999491
## 79  1890   26 MASCULINO    7000 UNIVERSITARIO INACTIVO 165246001  30082456
## 80  1913   26  FEMENINO    2000 UNIVERSITARIO INACTIVO  37861765   5915689
## 81  1928   40 MASCULINO    4000      PRIMARIA   ACTIVO  88818011         0
## 82  1972   46 MASCULINO    2000      PRIMARIA INACTIVO 171976702   1476558
## 83  1972   46 MASCULINO    2000      PRIMARIA INACTIVO  71929270   9202919
## 84  1972   46 MASCULINO    2000      PRIMARIA INACTIVO 122260252   8269280
## 85  1976   26 MASCULINO    8000      PRIMARIA INACTIVO 179030478  50554000
##    TIPO_PAGO
## 76   MENSUAL
## 77   MENSUAL
## 78   MENSUAL
## 79   MENSUAL
## 80   MENSUAL
## 81   MENSUAL
## 82   MENSUAL
## 83   MENSUAL
## 84   MENSUAL
## 85   MENSUAL

Punto 3 (0.5 pt)

Diga si el siguiente código es correcto o no, explique.

El código en si esta correcto si se utiliza el paquete dplyr, pero contiene un error en la última línea: la función view() no existe en R, ya que debe escribirse con mayúscula inicial como View(). Corrigiendo este detalle, el código realiza correctamente las acciones de agrupar por age, calcular la media de earn ignorando valores NA y el conteo de observaciones, ordenar en orden descendente por n y visualizar el resultado. El código corregido es:

#Se comenta el codigo
#    data3 <- data2 %>%
#      group_by(age) %>%
#      summarise(mean_earn = mean(earn, na.rm = TRUE), n = n()) %>%
#      arrange(-n) %>%
#      View()

Punto 4 (0.5 pt)

Explique que hace el siguiente código:

El código crea un tibble x con valores y algunos NA en las columnas x e y. Luego, reordena las filas utilizando arrange(is.na(y)), colocando primero las filas donde y tiene valores válidos (no NA) y después las filas con NA en y. La columna x no influye en el orden.

library(tibble)

# Crear el tibble
x <- tibble(
  x = c(1, NA, NA, 8, 4, NA),
  y = c(-1, NA, 2, NA, NA, 6)
)

# Reordenar las filas según si 'y' tiene NA o no
x %>%
  arrange(is.na(y)) 
## # A tibble: 6 × 2
##       x     y
##   <dbl> <dbl>
## 1     1    -1
## 2    NA     2
## 3    NA     6
## 4    NA    NA
## 5     8    NA
## 6     4    NA

Cambiar NA de X por 5

x <- x %>%
  mutate(x = ifelse(is.na(x), 5, x))

x
## # A tibble: 6 × 2
##       x     y
##   <dbl> <dbl>
## 1     1    -1
## 2     5    NA
## 3     5     2
## 4     8    NA
## 5     4    NA
## 6     5     6

Punto 5. Realice lo siguiente (2pts)

  1. Con la misma base de datos creada en el punto 2, encuentre una tabla de frecuencias para la variable TIPO_PAGO y haga un barplot para la frecuencia relativa y absoluta. Explique los resultados obtenidos.
Cartera<-read.csv(file="Cartera.csv",sep=";",dec=",")
Individuos<-read.csv(file="Individuos.csv",sep=";",dec=",")
CarteIndi<-merge(x=Individuos,y=Cartera, by.x="llave",
            by.y="Llave",all.x=T)

library(ggplot2)

# Tabla de frecuencias absolutas y relativas
freq_table <- table(CarteIndi$TIPO_PAGO)
freq_relative <- prop.table(freq_table)

# Crear un dataframe para ggplot
freq_df <- data.frame(
  TIPO_PAGO = names(freq_table),
  Frecuencia_Absoluta = as.vector(freq_table),
  Frecuencia_Relativa = as.vector(freq_relative)
)

print(freq_df)
##    TIPO_PAGO Frecuencia_Absoluta Frecuencia_Relativa
## 1      ANUAL                  23          0.14197531
## 2     DIARIO                   5          0.03086420
## 3    MENSUAL                  85          0.52469136
## 4  SEMESTRAL                  41          0.25308642
## 5 TRIMESTRAL                   8          0.04938272
ggplot(freq_df, aes(x = TIPO_PAGO, y = Frecuencia_Absoluta, fill = TIPO_PAGO)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  geom_text(aes(label = Frecuencia_Absoluta), vjust = -0.3, size = 4) + 
  labs(
    title = "Frecuencia Absoluta de TIPO_PAGO",
    x = "Tipo de Pago",
    y = "Frecuencia Absoluta"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_fill_brewer(palette = "Set3")

# Gráfico de frecuencias relativas
ggplot(freq_df, aes(x = TIPO_PAGO, y = Frecuencia_Relativa, fill = TIPO_PAGO)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  geom_text(aes(label = scales::percent(Frecuencia_Relativa)), vjust = -0.3, size = 4) + 
  labs(
    title = "Frecuencia Relativa de TIPO_PAGO",
    x = "Tipo de Pago",
    y = "Frecuencia Relativa"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_fill_brewer(palette = "Set3")

El resultado muestra que el tipo de pago mensual es el más utilizado, representando el 52.47% de los registros, seguido del pago semestral con un 25.31%. Los pagos anuales también son significativos, aunque menos frecuentes (14.20%), mientras que los pagos trimestrales (4.94%) y diarios (3.08%) tienen una baja participación.

Esto sugiere que los clientes prefieren opciones más manejables, como los pagos mensuales, o equilibradas, como los semestrales, posiblemente debido a su conveniencia y accesibilidad. En contraste, los pagos diarios y trimestrales son menos populares, lo que podría indicar oportunidades para explorar estrategias que impulsen su adopción, si resultan relevantes para el negocio.

  1. Haga un gráfico de dispersión para las variables Edad y Saldo y diga qué relación se observa y diga si eso era lo esperado.
library(ggplot2)

# Crear un gráfico de dispersión para Edad y Saldo
ggplot(CarteIndi, aes(x = Edad, y = SALDO)) +
  geom_point(alpha = 0.6, color = "blue") +
  labs(
    title = "Relación entre Edad y Saldo",
    x = "Edad",
    y = "Saldo"
  ) +
  theme_minimal()

  1. Haga una tabla de contingencias para dos variables categóricas de su elección y diga en que categorías se encuentra la mayor cantidad de personas y que porcentaje son.
tabla_contingencia <- table(CarteIndi$EDUCACION, CarteIndi$GENERO)

# Convertir a dataframe para facilitar el cálculo de totales y porcentajes
tabla_df <- as.data.frame.matrix(tabla_contingencia)
tabla_df$Total_Educacion <- rowSums(tabla_contingencia)  # Total por nivel educativo
tabla_df$Porcentaje <- (tabla_df$Total_Educacion / sum(tabla_df$Total_Educacion)) * 100

# Mostrar la tabla de contingencia
print(tabla_contingencia)
##                
##                 FEMENINO MASCULINO
##   BACHILLER           15         4
##   PRIMARIA            49        70
##   UNIVERSITARIO       16        10
# Encontrar la categoría con mayor cantidad de personas
max_categoria <- which(tabla_contingencia == max(tabla_contingencia), arr.ind = TRUE)
categoria_max <- tabla_contingencia[max_categoria]

cat("La categoría con mayor cantidad de personas es:",
    rownames(tabla_contingencia)[max_categoria[1, 1]], "y género",
    colnames(tabla_contingencia)[max_categoria[1, 2]],
    "con", max(tabla_contingencia), "personas, que representan el",
    round((max(tabla_contingencia) / sum(tabla_contingencia)) * 100, 2),
    "% del total.\n")
## La categoría con mayor cantidad de personas es: PRIMARIA y género MASCULINO con 70 personas, que representan el 42.68 % del total.
  1. Haga una regresión lineal con 2 variables (una categórica y otra numérica). Interprete
CarteIndi$GENERO <- as.factor(CarteIndi$GENERO)
modelo <- lm(SALDO ~ GENERO, data = CarteIndi)
summary(modelo)
## 
## Call:
## lm(formula = SALDO ~ GENERO, data = CarteIndi)
## 
## Residuals:
##        Min         1Q     Median         3Q        Max 
## -100860557  -49719261     159651   50989482  100158181 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     97205200    6795064  14.305   <2e-16 ***
## GENEROMASCULINO  4549217    9436510   0.482     0.63    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 60010000 on 160 degrees of freedom
##   (2 observations deleted due to missingness)
## Multiple R-squared:  0.00145,    Adjusted R-squared:  -0.00479 
## F-statistic: 0.2324 on 1 and 160 DF,  p-value: 0.6304