Práctica 01: Introducción a R, tidyverse y Datos Categóricos

Author

SOC3070 · Roberto Cantillan

Published

August 27, 2025


1. Introducción al tidyverse

¿Qué es tidyverse?

tidyverse es una colección de paquetes de R para ciencia de datos que comparten una filosofía común y gramática consistente.

Principios fundamentales:

  1. Tidy Data: Cada variable = columna, cada observación = fila
  2. Gramática consistente: Funciones siguen patrones predecibles
  3. Pipe operator (%>%): Encadena operaciones de manera legible
Code
# Paquetes principales del tidyverse
paquetes_core <- tibble(
  paquete = c("ggplot2", "dplyr", "tidyr", "readr", "purrr", "tibble", "stringr", "forcats"),
  funcion = c("Visualización", "Manipulación", "Reorganización", "Importar", 
              "Iteración", "Data frames", "Texto", "Factores")
)

print(paquetes_core)
#> # A tibble: 8 × 2
#>   paquete funcion       
#>   <chr>   <chr>         
#> 1 ggplot2 Visualización 
#> 2 dplyr   Manipulación  
#> 3 tidyr   Reorganización
#> 4 readr   Importar      
#> 5 purrr   Iteración     
#> 6 tibble  Data frames   
#> 7 stringr Texto         
#> 8 forcats Factores

El Operador Pipe (%>%)

Code
# Datos de ejemplo
datos <- tibble(
  nombre = c("Ana", "Luis", "Carmen", "Pedro"),
  edad = c(25, 32, 19, 45),
  salario = c(45000, 52000, 38000, 67000)
)

# Sin pipes (difícil de leer)
resultado_sin_pipes <- select(
  filter(
    mutate(datos, salario_miles = salario/1000), 
    edad > 20
  ), 
  nombre, edad, salario_miles
)

# Con pipes (fácil de leer)
resultado_con_pipes <- datos %>%
  mutate(salario_miles = salario/1000) %>%
  filter(edad > 20) %>%
  select(nombre, edad, salario_miles)

print(resultado_con_pipes)
#> # A tibble: 3 × 3
#>   nombre  edad salario_miles
#>   <chr>  <dbl>         <dbl>
#> 1 Ana       25            45
#> 2 Luis      32            52
#> 3 Pedro     45            67

2. Funciones Fundamentales de dplyr

Code
# Crear dataset de práctica
set.seed(123)
estudiantes <- tibble(
  id = 1:50,
  nombre = paste("Estudiante", 1:50),
  edad = sample(18:25, 50, replace = TRUE),
  carrera = sample(c("Sociología", "Psicología", "Economía", "Historia"), 50, replace = TRUE),
  promedio = round(rnorm(50, mean = 5.5, sd = 0.8), 1),
  creditos = sample(120:180, 50, replace = TRUE),
  beca = sample(c(TRUE, FALSE), 50, replace = TRUE, prob = c(0.3, 0.7))
)

glimpse(estudiantes)
#> Rows: 50
#> Columns: 7
#> $ id       <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18…
#> $ nombre   <chr> "Estudiante 1", "Estudiante 2", "Estudiante 3", "Estudiante 4…
#> $ edad     <int> 24, 24, 20, 23, 20, 19, 19, 23, 20, 22, 21, 23, 23, 18, 19, 2…
#> $ carrera  <chr> "Historia", "Sociología", "Economía", "Sociología", "Economía…
#> $ promedio <dbl> 5.7, 5.5, 5.5, 6.6, 5.3, 6.7, 4.3, 6.0, 5.6, 5.7, 5.8, 5.1, 5…
#> $ creditos <int> 149, 149, 171, 144, 135, 143, 173, 130, 167, 139, 159, 122, 1…
#> $ beca     <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,…

1. select() - Seleccionar Columnas

Code
# Selección básica
estudiantes %>% select(nombre, edad, carrera)
#> # A tibble: 50 × 3
#>   nombre        edad carrera   
#>   <chr>        <int> <chr>     
#> 1 Estudiante 1    24 Historia  
#> 2 Estudiante 2    24 Sociología
#> 3 Estudiante 3    20 Economía  
#> 4 Estudiante 4    23 Sociología
#> 5 Estudiante 5    20 Economía  
#> 6 Estudiante 6    19 Historia  
#> # ℹ 44 more rows
Code
# Selección con funciones auxiliares
estudiantes %>% select(starts_with("c"))  # Columnas que inician con 'c'
#> # A tibble: 50 × 2
#>   carrera    creditos
#>   <chr>         <int>
#> 1 Historia        149
#> 2 Sociología      149
#> 3 Economía        171
#> 4 Sociología      144
#> 5 Economía        135
#> 6 Historia        143
#> # ℹ 44 more rows
Code
estudiantes %>% select(where(is.numeric)) # Solo columnas numéricas
#> # A tibble: 50 × 4
#>      id  edad promedio creditos
#>   <int> <int>    <dbl>    <int>
#> 1     1    24      5.7      149
#> 2     2    24      5.5      149
#> 3     3    20      5.5      171
#> 4     4    23      6.6      144
#> 5     5    20      5.3      135
#> 6     6    19      6.7      143
#> # ℹ 44 more rows

2. filter() - Filtrar Filas

Code
# Filtros básicos
estudiantes %>% filter(carrera == "Sociología")
#> # A tibble: 15 × 7
#>      id nombre         edad carrera    promedio creditos beca 
#>   <int> <chr>         <int> <chr>         <dbl>    <int> <lgl>
#> 1     2 Estudiante 2     24 Sociología      5.5      149 FALSE
#> 2     4 Estudiante 4     23 Sociología      6.6      144 FALSE
#> 3     8 Estudiante 8     23 Sociología      6        130 FALSE
#> 4    10 Estudiante 10    22 Sociología      5.7      139 TRUE 
#> 5    11 Estudiante 11    21 Sociología      5.8      159 TRUE 
#> 6    15 Estudiante 15    19 Sociología      4.6      171 FALSE
#> # ℹ 9 more rows
Code
estudiantes %>% filter(promedio > 6.0)
#> # A tibble: 12 × 7
#>      id nombre         edad carrera    promedio creditos beca 
#>   <int> <chr>         <int> <chr>         <dbl>    <int> <lgl>
#> 1     4 Estudiante 4     23 Sociología      6.6      144 FALSE
#> 2     6 Estudiante 6     19 Historia        6.7      143 TRUE 
#> 3    19 Estudiante 19    20 Economía        6.2      161 FALSE
#> 4    20 Estudiante 20    20 Sociología      7.1      178 FALSE
#> 5    23 Estudiante 23    18 Economía        6.3      176 FALSE
#> 6    26 Estudiante 26    20 Psicología      6.3      165 TRUE 
#> # ℹ 6 more rows
Code
# Filtros múltiples
estudiantes %>% filter(carrera == "Economía" & beca == TRUE)
#> # A tibble: 3 × 7
#>      id nombre         edad carrera  promedio creditos beca 
#>   <int> <chr>         <int> <chr>       <dbl>    <int> <lgl>
#> 1    14 Estudiante 14    18 Economía      4.7      155 TRUE 
#> 2    25 Estudiante 25    22 Economía      4.9      127 TRUE 
#> 3    50 Estudiante 50    20 Economía      4.7      129 TRUE
Code
estudiantes %>% filter(edad <= 19 | promedio >= 6.5)
#> # A tibble: 18 × 7
#>      id nombre         edad carrera    promedio creditos beca 
#>   <int> <chr>         <int> <chr>         <dbl>    <int> <lgl>
#> 1     4 Estudiante 4     23 Sociología      6.6      144 FALSE
#> 2     6 Estudiante 6     19 Historia        6.7      143 TRUE 
#> 3     7 Estudiante 7     19 Psicología      4.3      173 FALSE
#> 4    14 Estudiante 14    18 Economía        4.7      155 TRUE 
#> 5    15 Estudiante 15    19 Sociología      4.6      171 FALSE
#> 6    20 Estudiante 20    20 Sociología      7.1      178 FALSE
#> # ℹ 12 more rows
Code
# Filtros avanzados
estudiantes %>% filter(carrera %in% c("Sociología", "Historia"))
#> # A tibble: 25 × 7
#>      id nombre         edad carrera    promedio creditos beca 
#>   <int> <chr>         <int> <chr>         <dbl>    <int> <lgl>
#> 1     1 Estudiante 1     24 Historia        5.7      149 FALSE
#> 2     2 Estudiante 2     24 Sociología      5.5      149 FALSE
#> 3     4 Estudiante 4     23 Sociología      6.6      144 FALSE
#> 4     6 Estudiante 6     19 Historia        6.7      143 TRUE 
#> 5     8 Estudiante 8     23 Sociología      6        130 FALSE
#> 6    10 Estudiante 10    22 Sociología      5.7      139 TRUE 
#> # ℹ 19 more rows
Code
estudiantes %>% filter(between(promedio, 5.0, 6.0))
#> # A tibble: 30 × 7
#>      id nombre        edad carrera    promedio creditos beca 
#>   <int> <chr>        <int> <chr>         <dbl>    <int> <lgl>
#> 1     1 Estudiante 1    24 Historia        5.7      149 FALSE
#> 2     2 Estudiante 2    24 Sociología      5.5      149 FALSE
#> 3     3 Estudiante 3    20 Economía        5.5      171 FALSE
#> 4     5 Estudiante 5    20 Economía        5.3      135 FALSE
#> 5     8 Estudiante 8    23 Sociología      6        130 FALSE
#> 6     9 Estudiante 9    20 Psicología      5.6      167 FALSE
#> # ℹ 24 more rows

3. mutate() - Crear/Modificar Columnas

Code
# Crear nuevas variables
estudiantes %>%
  mutate(
    promedio_centesimal = promedio * 10,
    edad_meses = edad * 12,
    beca_texto = if_else(beca, "Sí", "No")
  ) %>%
  select(nombre, promedio, promedio_centesimal, beca_texto)
#> # A tibble: 50 × 4
#>   nombre       promedio promedio_centesimal beca_texto
#>   <chr>           <dbl>               <dbl> <chr>     
#> 1 Estudiante 1      5.7                  57 No        
#> 2 Estudiante 2      5.5                  55 No        
#> 3 Estudiante 3      5.5                  55 No        
#> 4 Estudiante 4      6.6                  66 No        
#> 5 Estudiante 5      5.3                  53 No        
#> 6 Estudiante 6      6.7                  67 Sí        
#> # ℹ 44 more rows
Code
# Variables con lógica condicional
estudiantes %>%
  mutate(
    categoria = case_when(
      promedio >= 6.5 ~ "Excelente",
      promedio >= 6.0 ~ "Muy Bueno", 
      promedio >= 5.5 ~ "Bueno",
      promedio >= 5.0 ~ "Suficiente",
      TRUE ~ "Insuficiente"
    )
  ) %>%
  count(categoria)
#> # A tibble: 5 × 2
#>   categoria        n
#>   <chr>        <int>
#> 1 Bueno           16
#> 2 Excelente        6
#> 3 Insuficiente     8
#> 4 Muy Bueno        8
#> 5 Suficiente      12

4. arrange() - Ordenar Filas

Code
# Ordenamiento básico
estudiantes %>% arrange(edad) %>% select(nombre, edad)
#> # A tibble: 50 × 2
#>   nombre         edad
#>   <chr>         <int>
#> 1 Estudiante 14    18
#> 2 Estudiante 21    18
#> 3 Estudiante 23    18
#> 4 Estudiante 24    18
#> 5 Estudiante 31    18
#> 6 Estudiante 36    18
#> # ℹ 44 more rows
Code
# Ordenamiento múltiple
estudiantes %>% 
  arrange(carrera, desc(promedio)) %>% 
  select(nombre, carrera, promedio)
#> # A tibble: 50 × 3
#>   nombre        carrera  promedio
#>   <chr>         <chr>       <dbl>
#> 1 Estudiante 37 Economía      6.4
#> 2 Estudiante 23 Economía      6.3
#> 3 Estudiante 19 Economía      6.2
#> 4 Estudiante 38 Economía      5.8
#> 5 Estudiante 3  Economía      5.5
#> 6 Estudiante 5  Economía      5.3
#> # ℹ 44 more rows

5. summarise() - Resumir Datos

Code
# Estadísticas básicas
estudiantes %>%
  summarise(
    n = n(),
    edad_promedio = mean(edad),
    promedio_general = mean(promedio),
    con_beca = sum(beca)
  )
#> # A tibble: 1 × 4
#>       n edad_promedio promedio_general con_beca
#>   <int>         <dbl>            <dbl>    <int>
#> 1    50          21.0             5.61       15
Code
# Resúmenes por grupos
estudiantes %>%
  group_by(carrera) %>%
  summarise(
    n = n(),
    promedio_medio = round(mean(promedio), 2),
    pct_con_beca = round(mean(beca) * 100, 1),
    .groups = "drop"
  )
#> # A tibble: 4 × 4
#>   carrera        n promedio_medio pct_con_beca
#>   <chr>      <int>          <dbl>        <dbl>
#> 1 Economía      12           5.4          25  
#> 2 Historia      10           5.68         40  
#> 3 Psicología    13           5.64         30.8
#> 4 Sociología    15           5.71         26.7

3. Manipulación de Texto con stringr

Code
# Datos con problemas típicos de texto
datos_texto <- tibble(
  id = 1:6,
  nombre = c("  MARÍA josé  ", "juan carlos", "Ana Sofía    ", 
             "Pedro-Antonio", "carmen rosa", "LUIS ALBERTO"),
  email = c("maria@GMAIL.COM", "j.ruiz@hotmail.es  ", "ana@yahoo.com", 
            "pedro@uni.cl", "carmen@empresa.co", "luis@CORP.CL")
)

print(datos_texto)
#> # A tibble: 6 × 3
#>      id nombre           email                
#>   <int> <chr>            <chr>                
#> 1     1 "  MARÍA josé  " "maria@GMAIL.COM"    
#> 2     2 "juan carlos"    "j.ruiz@hotmail.es  "
#> 3     3 "Ana Sofía    "  "ana@yahoo.com"      
#> 4     4 "Pedro-Antonio"  "pedro@uni.cl"       
#> 5     5 "carmen rosa"    "carmen@empresa.co"  
#> 6     6 "LUIS ALBERTO"   "luis@CORP.CL"

Funciones Básicas de Limpieza

Code
datos_limpios <- datos_texto %>%
  mutate(
    # Limpiar espacios y capitalización
    nombre_limpio = str_trim(nombre) %>% str_to_title(),
    email_limpio = str_trim(email) %>% str_to_lower(),
    
    # Detectar patrones
    tiene_guion = str_detect(nombre, "-"),
    es_gmail = str_detect(email_limpio, "gmail"),
    
    # Extraer información
    primer_nombre = str_extract(nombre_limpio, "\\w+"),
    dominio = str_extract(email_limpio, "(?<=@)[^.]+")
  )

datos_limpios %>% select(nombre_limpio, email_limpio, primer_nombre, dominio)
#> # A tibble: 6 × 4
#>   nombre_limpio email_limpio      primer_nombre dominio
#>   <chr>         <chr>             <chr>         <chr>  
#> 1 María José    maria@gmail.com   María         gmail  
#> 2 Juan Carlos   j.ruiz@hotmail.es Juan          hotmail
#> 3 Ana Sofía     ana@yahoo.com     Ana           yahoo  
#> 4 Pedro-Antonio pedro@uni.cl      Pedro         uni    
#> 5 Carmen Rosa   carmen@empresa.co Carmen        empresa
#> 6 Luis Alberto  luis@corp.cl      Luis          corp

4. Trabajando con Factores usando forcats

Code
# Datos categóricos de ejemplo
set.seed(456)
encuesta <- tibble(
  id = 1:20,
  educacion = sample(c("Básica", "Media", "Técnica", "Universitaria", "Postgrado"), 20, replace = TRUE),
  satisfaccion = sample(c("Muy Insatisfecho", "Insatisfecho", "Neutral", "Satisfecho", "Muy Satisfecho"), 20, replace = TRUE),
  region = sample(c("Metropolitana", "Valparaíso", "Biobío", "Araucanía"), 20, replace = TRUE)
)

# Problema: orden alfabético no tiene sentido
encuesta %>% count(educacion, sort = TRUE)
#> # A tibble: 5 × 2
#>   educacion         n
#>   <chr>         <int>
#> 1 Postgrado         6
#> 2 Básica            5
#> 3 Técnica           4
#> 4 Media             3
#> 5 Universitaria     2

Creación y Manipulación de Factores

Code
encuesta_factores <- encuesta %>%
  mutate(
    # Factor con orden lógico
    educacion_factor = factor(
      educacion,
      levels = c("Básica", "Media", "Técnica", "Universitaria", "Postgrado")
    ),
    
    # Factor ordenado
    satisfaccion_factor = factor(
      satisfaccion,
      levels = c("Muy Insatisfecho", "Insatisfecho", "Neutral", "Satisfecho", "Muy Satisfecho"),
      ordered = TRUE
    )
  )

# Ahora el orden es correcto
encuesta_factores %>% 
  count(educacion_factor) %>%
  arrange(educacion_factor)
#> # A tibble: 5 × 2
#>   educacion_factor     n
#>   <fct>            <int>
#> 1 Básica               5
#> 2 Media                3
#> 3 Técnica              4
#> 4 Universitaria        2
#> 5 Postgrado            6

Reordenar y Agrupar Factores

Code
# Datos con muchas categorías
ventas <- tibble(
  producto = sample(c("Laptop", "Mouse", "Teclado", "Monitor", "Tablet", 
                     "Smartphone", "Auriculares", "Cámara", "USB"), 100, replace = TRUE)
)

ventas_agrupadas <- ventas %>%
  mutate(
    # Ordenar por frecuencia
    producto_freq = fct_infreq(factor(producto)),
    
    # Mantener solo top 5, agrupar resto
    producto_top5 = fct_lump_n(factor(producto), n = 5, other_level = "Otros"),
    
    # Colapsar categorías específicas
    categoria = fct_collapse(
      factor(producto),
      "Computación" = c("Laptop", "Mouse", "Teclado", "Monitor"),
      "Móviles" = c("Smartphone", "Tablet"),
      other_level = "Otros"
    )
  )

ventas_agrupadas %>% count(categoria, sort = TRUE)
#> # A tibble: 3 × 2
#>   categoria       n
#>   <fct>       <int>
#> 1 Computación    38
#> 2 Otros          33
#> 3 Móviles        29

5. Análisis con Datos Reales: GSS

Code
# Cargar datos GSS
data("gss_cat", package = "forcats")

# Exploración básica
glimpse(gss_cat)
#> Rows: 21,483
#> Columns: 9
#> $ year    <int> 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 20…
#> $ marital <fct> Never married, Divorced, Widowed, Never married, Divorced, Mar…
#> $ age     <int> 26, 48, 67, 39, 25, 25, 36, 44, 44, 47, 53, 52, 52, 51, 52, 40…
#> $ race    <fct> White, White, White, White, White, White, White, White, White,…
#> $ rincome <fct> $8000 to 9999, $8000 to 9999, Not applicable, Not applicable, …
#> $ partyid <fct> "Ind,near rep", "Not str republican", "Independent", "Ind,near…
#> $ relig   <fct> Protestant, Protestant, Protestant, Orthodox-christian, None, …
#> $ denom   <fct> "Southern baptist", "Baptist-dk which", "No denomination", "No…
#> $ tvhours <int> 12, NA, 2, 4, 1, NA, 3, NA, 0, 3, 2, NA, 1, NA, 1, 7, NA, 3, 3…

Análisis de Variables Categóricas

Code
# Función para análisis de frecuencias
analizar_variable <- function(data, var) {
  data %>%
    filter(!is.na({{var}})) %>%
    count({{var}}, sort = TRUE) %>%
    mutate(
      porcentaje = round(n / sum(n) * 100, 1),
      porcentaje_acum = cumsum(porcentaje)
    )
}

# Análisis de identificación partidaria
analisis_partido <- analizar_variable(gss_cat, partyid)
print(analisis_partido)
#> # A tibble: 10 × 4
#>    partyid                n porcentaje porcentaje_acum
#>    <fct>              <int>      <dbl>           <dbl>
#>  1 Independent         4119       19.2            19.2
#>  2 Not str democrat    3690       17.2            36.4
#>  3 Strong democrat     3490       16.2            52.6
#>  4 Not str republican  3032       14.1            66.7
#>  5 Ind,near dem        2499       11.6            78.3
#>  6 Strong republican   2314       10.8            89.1
#>  7 Ind,near rep        1791        8.3            97.4
#>  8 Other party          393        1.8            99.2
#>  9 No answer            154        0.7            99.9
#> 10 Don't know             1        0              99.9
Code
# Análisis de religión (top 8)
analisis_religion <- analizar_variable(gss_cat, relig)
print(head(analisis_religion, 8))
#> # A tibble: 8 × 4
#>   relig                       n porcentaje porcentaje_acum
#>   <fct>                   <int>      <dbl>           <dbl>
#> 1 Protestant              10846       50.5            50.5
#> 2 Catholic                 5124       23.9            74.4
#> 3 None                     3523       16.4            90.8
#> 4 Christian                 689        3.2            94  
#> 5 Jewish                    388        1.8            95.8
#> 6 Other                     224        1              96.8
#> 7 Buddhism                  147        0.7            97.5
#> 8 Inter-nondenominational   109        0.5            98
Code
# Análisis temporal simple
evolucion_simple <- gss_cat %>%
  filter(!is.na(partyid)) %>%
  mutate(
    partido_simple = case_when(
      str_detect(partyid, "republican") ~ "Republicano",
      str_detect(partyid, "democrat") ~ "Demócrata", 
      str_detect(partyid, "Independent") ~ "Independiente",
      TRUE ~ "Otros"
    )
  ) %>%
  count(year, partido_simple) %>%
  group_by(year) %>%
  mutate(porcentaje = round(n / sum(n) * 100, 1)) %>%
  ungroup()

# Mostrar tendencia para Independientes
evolucion_simple %>%
  filter(partido_simple == "Independiente") %>%
  select(year, porcentaje) %>%
  arrange(year)
#> # A tibble: 8 × 2
#>    year porcentaje
#>   <int>      <dbl>
#> 1  2000       20.1
#> 2  2002       19.1
#> 3  2004       16.7
#> 4  2006       22.1
#> 5  2008       15.9
#> 6  2010       17.6
#> 7  2012       18.9
#> 8  2014       19.8

6. Ejercicios Prácticos

EJERCICIO 1: Análisis Básico

Usando el dataset estudiantes, realiza las siguientes tareas:

  1. Filtra estudiantes de “Sociología” con promedio mayor a 5.5
  2. Crea una nueva variable categoria_edad que clasifique:
    • “Joven”: edad <= 20
    • “Adulto”: edad > 20
  3. Calcula el promedio de créditos por carrera
  4. Ordena las carreras por promedio de notas (descendente)

Escribe el código para cada tarea.

SOLUCIÓN EJERCICIO 1:

Code
# Tarea 1: Filtrar estudiantes
estudiantes %>%
  filter(carrera == "Sociología", promedio > 5.5) %>%
  select(nombre, carrera, promedio)
#> # A tibble: 9 × 3
#>   nombre        carrera    promedio
#>   <chr>         <chr>         <dbl>
#> 1 Estudiante 4  Sociología      6.6
#> 2 Estudiante 8  Sociología      6  
#> 3 Estudiante 10 Sociología      5.7
#> 4 Estudiante 11 Sociología      5.8
#> 5 Estudiante 17 Sociología      5.9
#> 6 Estudiante 20 Sociología      7.1
#> 7 Estudiante 40 Sociología      6.4
#> 8 Estudiante 43 Sociología      5.7
#> 9 Estudiante 47 Sociología      7.2
Code
# Tarea 2: Crear categoría de edad
estudiantes %>%
  mutate(
    categoria_edad = if_else(edad <= 20, "Joven", "Adulto")
  ) %>%
  count(categoria_edad)
#> # A tibble: 2 × 2
#>   categoria_edad     n
#>   <chr>          <int>
#> 1 Adulto            25
#> 2 Joven             25
Code
# Tarea 3: Promedio de créditos por carrera
estudiantes %>%
  group_by(carrera) %>%
  summarise(promedio_creditos = round(mean(creditos), 1), .groups = "drop")
#> # A tibble: 4 × 2
#>   carrera    promedio_creditos
#>   <chr>                  <dbl>
#> 1 Economía                152.
#> 2 Historia                146.
#> 3 Psicología              154.
#> 4 Sociología              157.
Code
# Tarea 4: Carreras ordenadas por promedio de notas
estudiantes %>%
  group_by(carrera) %>%
  summarise(promedio_notas = round(mean(promedio), 2), .groups = "drop") %>%
  arrange(desc(promedio_notas))
#> # A tibble: 4 × 2
#>   carrera    promedio_notas
#>   <chr>               <dbl>
#> 1 Sociología           5.71
#> 2 Historia             5.68
#> 3 Psicología           5.64
#> 4 Economía             5.4

EJERCICIO 2: Manipulación de Texto y Factores

Con los datos de encuesta:

  1. Convierte educacion a factor con orden correcto
  2. Agrupa las regiones en dos categorías: “Centro” (Metropolitana, Valparaíso) y “Sur” (Biobío, Araucanía)
  3. Calcula el porcentaje de personas “Satisfechas” o “Muy Satisfechas” por región agrupada
  4. Identifica la combinación educación-satisfacción más común

Escribe el código paso a paso.

SOLUCIÓN EJERCICIO 2:

Code
# Tarea 1: Factor ordenado de educación
encuesta_factor <- encuesta %>%
  mutate(
    educacion_ordenada = factor(
      educacion,
      levels = c("Básica", "Media", "Técnica", "Universitaria", "Postgrado")
    )
  )

levels(encuesta_factor$educacion_ordenada)
#> [1] "Básica"        "Media"         "Técnica"       "Universitaria"
#> [5] "Postgrado"
Code
# Tarea 2: Agrupar regiones
encuesta_agrupada <- encuesta_factor %>%
  mutate(
    region_agrupada = case_when(
      region %in% c("Metropolitana", "Valparaíso") ~ "Centro",
      region %in% c("Biobío", "Araucanía") ~ "Sur",
      TRUE ~ "Otros"
    )
  )

encuesta_agrupada %>% count(region_agrupada)
#> # A tibble: 2 × 2
#>   region_agrupada     n
#>   <chr>           <int>
#> 1 Centro              8
#> 2 Sur                12
Code
# Tarea 3: Porcentaje satisfechos por región
satisfaccion_region <- encuesta_agrupada %>%
  mutate(
    satisfecho = satisfaccion %in% c("Satisfecho", "Muy Satisfecho")
  ) %>%
  group_by(region_agrupada) %>%
  summarise(
    pct_satisfecho = round(mean(satisfecho) * 100, 1),
    .groups = "drop"
  )

print(satisfaccion_region)
#> # A tibble: 2 × 2
#>   region_agrupada pct_satisfecho
#>   <chr>                    <dbl>
#> 1 Centro                    12.5
#> 2 Sur                       41.7
Code
# Tarea 4: Combinación más común
combinacion_comun <- encuesta %>%
  count(educacion, satisfaccion, sort = TRUE) %>%
  slice_head(n = 1)

print(combinacion_comun)
#> # A tibble: 1 × 3
#>   educacion satisfaccion         n
#>   <chr>     <chr>            <int>
#> 1 Básica    Muy Insatisfecho     4

EJERCICIO 3: Análisis GSS

Con el dataset gss_cat:

  1. Encuentra las 5 denominaciones religiosas más comunes
  2. Calcula el porcentaje de personas por raza en cada década (años terminados en 0)
  3. Crea una tabla que muestre religión vs identificación partidaria (solo las 3 religiones y 3 partidos más comunes)
  4. Identifica si hay cambios en el estado civil a lo largo del tiempo

SOLUCIÓN EJERCICIO 3:

Code
# Tarea 1: Top 5 religiones
top_religiones <- gss_cat %>%
  count(relig, sort = TRUE) %>%
  slice_head(n = 5)

print(top_religiones)
#> # A tibble: 5 × 2
#>   relig          n
#>   <fct>      <int>
#> 1 Protestant 10846
#> 2 Catholic    5124
#> 3 None        3523
#> 4 Christian    689
#> 5 Jewish       388
Code
# Tarea 2: Raza por década
raza_decada <- gss_cat %>%
  filter(year %% 10 == 0) %>%  # Años terminados en 0
  count(year, race) %>%
  group_by(year) %>%
  mutate(porcentaje = round(n / sum(n) * 100, 1)) %>%
  ungroup() %>%
  arrange(year, desc(porcentaje))

print(raza_decada)
#> # A tibble: 6 × 4
#>    year race      n porcentaje
#>   <int> <fct> <int>      <dbl>
#> 1  2000 White  2213       78.6
#> 2  2000 Black   429       15.2
#> 3  2000 Other   175        6.2
#> 4  2010 White  1550       75.8
#> 5  2010 Black   311       15.2
#> 6  2010 Other   183        9
Code
# Tarea 3: Tabla religión vs partido (top 3 cada uno)
top3_religion <- gss_cat %>% count(relig, sort = TRUE) %>% slice_head(n = 3) %>% pull(relig)
top3_partido <- gss_cat %>% count(partyid, sort = TRUE) %>% slice_head(n = 3) %>% pull(partyid)

tabla_religion_partido <- gss_cat %>%
  filter(relig %in% top3_religion, partyid %in% top3_partido) %>%
  count(relig, partyid) %>%
  group_by(relig) %>%
  mutate(porcentaje = round(n / sum(n) * 100, 1)) %>%
  ungroup()

print(tabla_religion_partido)
#> # A tibble: 9 × 4
#>   relig      partyid              n porcentaje
#>   <fct>      <fct>            <int>      <dbl>
#> 1 None       Independent        984       46.7
#> 2 None       Not str democrat   567       26.9
#> 3 None       Strong democrat    554       26.3
#> 4 Catholic   Independent       1045       37.2
#> 5 Catholic   Not str democrat  1044       37.2
#> 6 Catholic   Strong democrat    720       25.6
#> 7 Protestant Independent       1683       32  
#> 8 Protestant Not str democrat  1718       32.6
#> 9 Protestant Strong democrat   1866       35.4
Code
# Tarea 4: Estado civil por tiempo
marital_tiempo <- gss_cat %>%
  count(year, marital) %>%
  group_by(year) %>%
  mutate(porcentaje = round(n / sum(n) * 100, 1)) %>%
  ungroup() %>%
  filter(marital %in% c("Married", "Never married", "Divorced"))

# Mostrar tendencia para "Never married"
marital_tiempo %>%
  filter(marital == "Never married") %>%
  select(year, porcentaje) %>%
  arrange(year) %>%
  slice(c(1:3, (n()-2):n()))  # Primeros 3 y últimos 3
#> # A tibble: 6 × 2
#>    year porcentaje
#>   <int>      <dbl>
#> 1  2000       25.3
#> 2  2002       25.6
#> 3  2004       22  
#> 4  2010       27.6
#> 5  2012       26.6
#> 6  2014       26.6

7. Resumen

Funciones Clave por Paquete

Code
# Resumen de funciones principales
resumen_funciones <- tribble(
  ~paquete, ~funcion, ~proposito,
  "dplyr", "select()", "Seleccionar columnas",
  "dplyr", "filter()", "Filtrar filas", 
  "dplyr", "mutate()", "Crear/modificar variables",
  "dplyr", "arrange()", "Ordenar datos",
  "dplyr", "summarise()", "Resumir datos",
  "dplyr", "group_by()", "Agrupar para operaciones",
  "stringr", "str_detect()", "Detectar patrones",
  "stringr", "str_replace()", "Reemplazar texto",
  "stringr", "str_trim()", "Eliminar espacios",
  "forcats", "factor()", "Crear factores",
  "forcats", "fct_relevel()", "Reordenar niveles",
  "forcats", "fct_lump()", "Agrupar categorías raras"
)

print(resumen_funciones)
#> # A tibble: 12 × 3
#>   paquete funcion     proposito                
#>   <chr>   <chr>       <chr>                    
#> 1 dplyr   select()    Seleccionar columnas     
#> 2 dplyr   filter()    Filtrar filas            
#> 3 dplyr   mutate()    Crear/modificar variables
#> 4 dplyr   arrange()   Ordenar datos            
#> 5 dplyr   summarise() Resumir datos            
#> 6 dplyr   group_by()  Agrupar para operaciones 
#> # ℹ 6 more rows