Sesión 4

Importar y organizar datos: Excel, CSV y proyectos de R

Juan David Leongómez

Universidad El Bosque

10 de junio de 2026

Agenda

  • Reto 1: el concurso de la figura más fea
  • Proyectos de R y rutas relativas
  • Importar CSV: read_csv() y el problema que tenemos en español
  • Importar Excel: read_excel() y los argumentos importantes
  • Guardar datos procesados
  • Un flujo de trabajo reproducible

Reto 1

El concurso de la figura más fea

Las presentaciones

Cada persona tiene máximo 3 minutos:

  1. Explica brevemente qué decisiones tomaste para hacerla horrible
  2. Al final el grupo vota por la más fea

Mientras presentas, el script estará visible para que puedas explicarlo y por si alguien quiere ver el código de algún truco que usaste.

→ Abrir presentación de figuras

Parte 1

Proyectos de R

El error más común al empezar

Abrir un archivo sin proyecto lleva a escribir la ruta completa:

notas <- read_csv("C:/Users/Ana/Documents/Uni/Tercer semestre/datos/notas.csv")

Ese código solo funciona en el computador de Ana, en esa sesión. Al día siguiente, si mueve la carpeta, ya no funcionará. En el computador de otra persona, nunca funciona.

La solución no es poner la ruta completa, sino fijar un punto de referencia y usar rutas relativas.

Rutas relativas vs. absolutas

Ruta absoluta · desde la raíz del sistema

Windows: C:/Users/Ana/Documents/Uni/Tercer semestre/datos/notas.csv
Linux/Mac: /home/ana/uni/tercer_semestre/datos/notas.csv

Solo funciona en ese computador y esa carpeta. Si cambia alguno, se rompe.

Ruta relativa · desde una carpeta de referencia

datos/notas.csv (¡funciona igual en Windows, Linux o Mac!)

Funciona en cualquier computador, siempre que haya una referencia fija desde la que partir.

📁 C:/Users/Ana/Documents/…
└─ 📁 Tercer semestre/
└─ 📁 mi_proyecto/
└─ 📁 datos/
└─ 📄 notas.csv
solo en este equipo directorio de trabajo ruta relativa

El directorio de trabajo

Esa carpeta de referencia se llama directorio de trabajo (en R, working directory o wd). Puedes verla con:

getwd()
[1] "C:/Users/Ana/Documents"

El problema es que el directorio de trabajo varía según cómo abriste R, y rara vez coincide con donde guardaste los archivos del proyecto. Por eso una ruta como "datos/notas.csv" falla:

Error: cannot open file 'datos/notas.csv': No such file or directory

Lo que necesitas es una forma de fijar el directorio de trabajo en la carpeta de tu proyecto, de forma automática y permanente.

¿Qué es un proyecto de R?

Un archivo .Rproj convierte una carpeta en el punto de partida de tu sesión de trabajo.

Al abrir el proyecto, RStudio:

  1. Fija el directorio de trabajo en esa carpeta
  2. Restaura el script y el entorno de la sesión anterior
  3. Permite usar rutas relativas desde esa carpeta
# Con el proyecto abierto, esto funciona en cualquier computador
notas <- read_csv("datos/notas.csv")

Crear proyecto: File > New Project… > New Directory > New Project.

Dale un nombre sin espacios (será el nombre de la carpeta), y selecciona dentro de la ubicación de esa nueva carpeta en tu computador

Estructura del proyecto del curso

Esta es la estructura que usaremos hasta el final. Los documentos Quarto y la bibliografía van en la raíz, junto al .Rproj:

📁 curso_r/
├── 📄 curso_r.Rproj ← punto de partida
├── 📝 mi_reporte.qmd ← documentos Quarto en la raíz (s06+)
├── 📄 referencias.bib ← bibliografía en la raíz (s07+)
├── 📁 datos/ ← archivos originales (nunca se tocan)
├── 📁 figuras/ ← figuras exportadas con ggsave()
└── 📁 scripts/ ← archivos .R

¿Quieres la estructura ya lista? Descárgala en github.com/JDLeongomez/curso-r/tree/main/plantilla_proyecto, extrae el ZIP y renombra la carpeta curso_r.

Actividad · 7 min

Crea tu proyecto del curso

  1. File > New Project… > New Directory > New Project
  2. Nómbralo curso_r y elige una ubicación fácil de encontrar
  3. Dentro del proyecto, crea las carpetas datos/, figuras/ y scripts/
  4. Abre un script nuevo (File > New File > R Script) y guárdalo en scripts/ como sesion4.R
  5. Descarga estos archivos y ponlos en la carpeta datos/ del proyecto:

Parte 2

Importar CSV

¿Qué es un archivo CSV?

CSV (Comma-Separated Values) es texto plano donde cada línea es una observación y las columnas se separan con un carácter delimitador. El formato clásico usa coma como separador y punto como decimal:

id,carrera,estadistica,metodologia
1,Psicología,4.8,3.5
2,Medicina,3.7,4.1

A diferencia de Excel, no incluye fórmulas, colores ni metadatos ocultos. Ves exactamente lo que contiene el archivo… ¡sin redondear valores ni asumir que algo es una $%@! fecha! 😠.

read_csv(): el formato internacional

read_csv() espera coma como separador y punto como decimal (estándar internacional más común):

library(tidyverse)

notas <- read_csv("datos/notas.csv")
glimpse(notas)
Rows: 20
Columns: 1
$ `id;carrera;estadistica;metodologia;seminario` <chr> "1;Psicología;4,8;3,5;4…

Las columnas numéricas se leen como texto (<chr>) porque el separador es ; y el decimal es ,. Nada funciona.

El problema para quienes hablamos español

En Excel configurado en español, al exportar a CSV se usa punto y coma como separador y coma como decimal:

id;carrera;estadistica;metodologia
1;Psicología;4,8;3,5

La solución es read_csv2(), que asume exactamente ese formato:

notas <- read_csv2("datos/notas.csv")
glimpse(notas)
Rows: 20
Columns: 5
$ id          <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,…
$ carrera     <chr> "Psicología", "Medicina", "Enfermería", "Psicología", "Med…
$ estadistica <dbl> 4.8, 3.7, 4.2, 3.3, 2.8, 4.5, 3.9, 4.1, 3.6, 4.7, 2.5, 4.0…
$ metodologia <dbl> 3.5, 4.1, 4.0, NA, 3.2, 4.3, 3.7, 3.8, 3.4, 4.5, 2.8, 4.2,…
$ seminario   <dbl> 4.2, 3.9, 4.5, 3.8, 3.5, 4.7, NA, 4.0, 3.9, 4.8, 3.1, 3.7,…

Ahora estadistica, metodologia y seminario son numéricas (<dbl>).

Argumentos útiles de read_csv() y read_csv2()

Argumento Qué hace Ejemplo
skip Omite las primeras n filas skip = 2
na Define qué valores se tratan como NA na = c("", "N/A", "nd")
col_names Proporciona nombres de columna col_names = c("id", "nota")
n_max Lee solo las primeras n observaciones n_max = 100
col_types Define el tipo de cada columna col_types = "ccd"

Cuando el archivo tiene un encabezado raro o filas de información antes de los datos, skip es la primera herramienta. Prueba con skip = 1, revisa el resultado, y ajusta.

Actividad · 7 min

Carga y explora notas.csv

⬇ Descargar notas.csv (si no lo has hecho)

Guarda el archivo en la carpeta datos/ de tu proyecto. Luego en tu script:

  1. Carga el archivo con read_csv2() y asígnalo a notas
  2. Usa glimpse() o View() para verificar que las columnas numéricas son <dbl>
  3. Calcula el promedio de la columna estadistica por carrera usando group_by() + summarise()

notas.csv tiene algunos NA. Si mean() genera NA en lugar de algún número, añade na.rm = TRUE: mean(estadistica, na.rm = TRUE).

Parte 3

Importar Excel

read_excel(): recordatorio rápido

Ya lo usamos en la Sesión 3 con encuesta_bruta.xlsx. La función viene del paquete readxl:

library(readxl)

# Carga la primera hoja por defecto
asistencia <- read_excel("datos/registro.xlsx")
glimpse(asistencia)
Rows: 20
Columns: 7
$ id      <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,…
$ carrera <chr> "Psicología", "Medicina", "Enfermería", "Psicología", "Medicin…
$ s01     <dbl> 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1
$ s02     <dbl> 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1
$ s03     <dbl> 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1
$ s04     <dbl> 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1
$ total   <dbl> 4, 3, 4, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 3, 4, 4

Sin argumentos extra, carga la primera hoja del archivo.

Múltiples hojas: el argumento sheet

Un libro Excel puede tener varias hojas. Primero, mira qué hojas hay:

excel_sheets("datos/registro.xlsx")
[1] "Asistencia"     "Calificaciones"

Luego elige la que necesitas:

calificaciones <- read_excel(
    "datos/registro.xlsx",
    sheet = "Calificaciones",
    skip  = 2
)
glimpse(calificaciones)
Rows: 20
Columns: 5
$ id       <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18…
$ carrera  <chr> "Psicología", "Medicina", "Enfermería", "Psicología", "Medici…
$ parcial1 <dbl> 3.8, 4.2, 3.5, NA, 3.9, 4.1, 3.7, 4.0, 3.6, 4.5, 2.9, 4.3, 3.…
$ parcial2 <dbl> 4.1, 3.9, 4.0, 3.5, 4.2, 4.4, 3.8, 4.1, 3.7, 4.6, 3.1, 4.0, 3…
$ final    <dbl> NA, 4.0, 3.8, 3.7, 4.0, 4.2, 3.7, 4.0, NA, 4.5, 3.0, 4.1, 3.8…

skip = 2 omite la fila de título y la fila vacía, igual que en encuesta_bruta.xlsx.

Argumentos útiles de read_excel()

Argumento Qué hace Ejemplo
sheet Nombre o número de hoja sheet = "Datos" o sheet = 2
skip Omite las primeras n filas skip = 2
range Rango de celdas específico range = "A3:F50"
na Valores que se tratarán como NA na = c("", "n/d")
col_types Tipo forzado por columna col_types = c("numeric", "text", "skip")

Cuando hay columnas extra por anotaciones fuera de la tabla (las columnas ...15, ...16 de la Sesión 3), usa select(-starts_with("...")) después de cargar para eliminarlas.

Actividad · 7 min

Carga ambas hojas de registro.xlsx

⬇ Descargar registro.xlsx (si no lo has hecho)

Guarda el archivo en datos/. Luego:

  1. Usa excel_sheets() para ver los nombres de las hojas
  2. Carga "Asistencia" sin argumentos extra. Asígnalo a un objeto
  3. Carga "Calificaciones" con skip = 2. Asígnalo a otro objeto
  4. Confirma la estructura de los dos objetos con glimpse() o View()

Parte 4

Guardar y organizar

Guardar datos procesados

Una vez limpios y transformados, puedes guardar los datos para no tener que repetir el proceso cada vez.

CSV: portátil y universal

# Para compartir con otros programas
write_csv(notas, "datos/notas_limpias.csv")

# Para CSV latinoamericano
write_csv2(notas, "datos/notas_limpias.csv")

Cualquier programa puede abrirlo.

RDS: rápido y fiel

# Guarda el objeto exactamente como está en R
saveRDS(notas, "datos/notas_limpias.rds")

# Para cargarlo después
notas <- readRDS("datos/notas_limpias.rds")

Conserva tipos, factores y atributos. Solo funciona en R.

Guarda los datos procesados en datos/ con un nombre diferente al original (por ejemplo, notas_limpias.csv). El archivo original nunca se toca.

El script autocontenido

Un buen script de análisis sigue siempre el mismo esquema:

# 1. Paquetes
library(tidyverse)
library(readxl)

# 2. Importar datos originales
notas <- read_csv2("datos/notas.csv")

# 3. Limpiar y transformar
notas <- notas |>
    mutate(promedio = (estadistica + metodologia + seminario) / 3)

# 4. Analizar
notas |>
    group_by(carrera) |>
    summarise(promedio_carrera = mean(promedio, na.rm = TRUE))

# 5. Exportar resultados (figuras, datos procesados)
write_csv(notas, "datos/notas_procesadas.csv")

Cualquier persona que tenga el proyecto y ejecute este script obtiene exactamente el mismo resultado.

Antes de terminar…

Quiz rápido

Quiz · 1 de 3

Tienes un CSV exportado desde Excel en español con esta primera línea: id;carrera;nota. ¿Cuál función usas para cargarlo correctamente?

    1. read_csv("datos/archivo.csv")
    1. read_csv2("datos/archivo.csv")
    1. read_excel("datos/archivo.csv")
    1. read_table("datos/archivo.csv")

b) read_csv2() espera punto y coma como separador y coma como decimal, el estándar de Excel configurado en español. read_csv() esperaría coma como separador y devolvería todo en una sola columna.

Quiz · 2 de 3

Un archivo Excel tiene tres hojas: "Datos", "Resumen" y "Notas". La hoja "Resumen" empieza con dos filas de encabezado antes de los datos. ¿Cuál código la carga correctamente?

    1. read_excel("archivo.xlsx")
    1. read_excel("archivo.xlsx", sheet = "Resumen")
    1. read_excel("archivo.xlsx", sheet = "Resumen", skip = 2)
    1. read_excel("archivo.xlsx", skip = 2)

c) Necesitas sheet = "Resumen" para seleccionar la hoja correcta (sin esto carga la primera) y skip = 2 para omitir las dos filas de encabezado antes de los datos.

Quiz · 3 de 3

¿Cuál es la ventaja principal de trabajar dentro de un proyecto .Rproj?

    1. El código se ejecuta más rápido porque R optimiza automáticamente
    1. Las rutas relativas funcionan desde cualquier computador sin modificar el código
    1. Se instalan automáticamente todos los paquetes necesarios
    1. No es necesario guardar los scripts manualmente

b) El proyecto fija el directorio de trabajo en su propia carpeta. Así, read_csv("datos/notas.csv") funciona igual en tu computador, en el de un colega o en el tuyo dentro de seis meses, siempre que la estructura de carpetas se mantenga.

A practicar

Antes de la próxima sesión, crea un proyecto .Rproj nuevo e importa al menos un archivo externo con una ruta relativa.

Experimenta con:

  • Un archivo CSV propio o descargado: read_csv("datos/mi_archivo.csv")
  • Un archivo Excel: read_excel("datos/mi_archivo.xlsx", sheet = 1)
  • Explorar la estructura con glimpse(), names() y head()
  • Limpiar al menos un problema típico: nombres con espacios, filas sobrantes, tipos mal asignados
  • Exportar el resultado con write_csv(), write_csv2() o saveRDS()

Si no tienes un archivo propio, usa encuesta_bruta.xlsx de la Sesión 3 desde tu proyecto nuevo y verifica que la ruta relativa funciona sin modificar el código.

Hasta la próxima sesión

¡Gracias!

jdleongomez.github.io/curso-r