Carga de datos

Directorio de trabajo

Antes de importar datos a R, es recomendable definir una carpeta de trabajo (directorio). Esa carpeta será el lugar donde:

  • Guardaremos nuestros conjuntos de datos (archivos que vamos a analizar).

  • R buscará automáticamente los archivos cuando le indiquemos cargarlos.

  • Se guardarán los resultados que generemos (por ejemplo: tablas, gráficos o bases de datos nuevas).

Esto facilita mantener todo el trabajo organizado en un mismo lugar.

Por defecto, R selecciona una carpeta. Para ver cuál es corremos la siguiente función:

getwd()
## [1] "C:/Users/diori/Documents/CursoR_docentes"

Para cambiar la carpeta, usamos la función setwd("ruta") o podemos hacerlo desde SessionSet Working DirectoryChoose Directory…

setwd("~/CursoR_docentes")

Tip: Es útil crear una carpeta para cada curso, proyecto o análisis y guardar todo ahí dentro (datos, scripts y resultados).

Formatos comunes de archivos

R permite importar distintos tipos de archivos. A continuación, veremos cómo cargar los tres más comunes: .txt, .csv y Excel.

Además de cargar los datos escribiendo código, en RStudio existe una herramienta visual llamada Import Dataset, que genera automáticamente el código por nosotros.

Para usarla:

  1. Ir a FileImport Dataset.

  2. Elegir el tipo de archivo:

  • From Text (base): Para archivos .txt.

  • From Text (readr): Para archivos .csv.

  • From Excel: Para archivos de Excel.

  1. Buscar y seleccionar el archivo.

  2. RStudio mostrará una vista previa de los datos. Desde allí podemos:

  • Elegir si los datos tienen encabezado.

  • Cambiar el separador (por ejemplo: coma, punto y coma, tabulación).

  • Elegir la hoja de Excel (si corresponde).

  1. Si todo está bien, hacemos clic en Import.

  2. Los datos se cargarán y RStudio mostrará el código que se ejecutó (esto es útil para aprender).

Incluso podemos copiar el código que se ejecutó para volverlo a correr cuando deseemos.

Desde un archivo txt

Existen varias funciones en R para importar archivos de texto (.txt). Una de las más utilizadas es read.table(), que permite leer archivos especificando el nombre del archivo, si el archivo contiene un encabezado (header = TRUE) y el tipo de separador entre los campos (argumento sep). En el caso de archivos .txt separados por tabulaciones, es habitual utilizar sep = "\t". Una alternativa más sencilla para este tipo de archivos es la función read.delim(), que está pensada específicamente para leer archivos delimitados por tabulaciones. Esta función asume por defecto sep = "\t" y header = TRUE, por lo que no es necesario indicar estos argumentos manualmente.

read.table(file,           # Archivo de datos TXT indicado como string o ruta completa al archivo
           header = FALSE, # Si se muestra el encabezado (TRUE) o no (FALSE)
           sep = "",       # Separador de las columnas del archivo
           dec = ".")      # Carácter utilizado para separar decimales de los números en el archivo
datos_txt <- read.table("datos_txt.txt", header = TRUE, sep = "\t")
head(datos_txt)
##                     Nombre_Fondo            Tipo_Fondo Activos_Netos
## 1    American Century Intl. Disc Capital internacional         14.37
## 2 American Century Tax-Free Bond            Renta fija         10.73
## 3         American Century Ultra      Capital nacional         24.94
## 4              Artisan Small Cap      Capital nacional         16.92
## 5                Brown Cap Small      Capital nacional         35.73
## 6             DFA U.S. Micro Cap      Capital nacional         13.47
##   Rentabilidad_5_Años Ratio_Gastos Ranking_Morningstar
## 1               30.53         1.41              3-star
## 2                3.34         0.49              4-star
## 3               10.88         0.99              3-star
## 4               15.67         1.18              3-star
## 5               15.85         1.20              4-star
## 6               17.23         0.53              3-star

O también

datos_txt <- read.delim("datos_txt.txt")
head(datos_txt)
##                     Nombre_Fondo            Tipo_Fondo Activos_Netos
## 1    American Century Intl. Disc Capital internacional         14.37
## 2 American Century Tax-Free Bond            Renta fija         10.73
## 3         American Century Ultra      Capital nacional         24.94
## 4              Artisan Small Cap      Capital nacional         16.92
## 5                Brown Cap Small      Capital nacional         35.73
## 6             DFA U.S. Micro Cap      Capital nacional         13.47
##   Rentabilidad_5_Años Ratio_Gastos Ranking_Morningstar
## 1               30.53         1.41              3-star
## 2                3.34         0.49              4-star
## 3               10.88         0.99              3-star
## 4               15.67         1.18              3-star
## 5               15.85         1.20              4-star
## 6               17.23         0.53              3-star

Desde un archivo CSV

Otra función comúnmente utilizada en R es read.csv(), que permite importar archivos separados por comas (.csv). read.csv() está diseñada específicamente para leer archivos CSV, asumiendo por defecto sep = ",", dec = "." y header = TRUE. Esto significa que, en la mayoría de los casos, sólo es necesario indicar el nombre del archivo, sin especificar otros argumentos adicionales. Este formato es muy utilizado para intercambiar datos entre distintos programas y es compatible con la mayoría de las hojas de cálculo y bases de datos.

read.csv(file,                 # Nombre del archivo o ruta completa del archivo
         header = TRUE,        # Leer el encabezado (TRUE) o no (FALSE)
         sep = ",",            # Separador de los valores
         quote = "\"'",        # Carácter de citaciones
         dec = ".",            # Punto decimal
         fill = TRUE,          # Rellenar celdas vacías (TRUE) o no (FALSE)
         comment.char = "",    # Carácter de los comentarios o cadenas vacías
         encoding = "unknown", # Codificación del archivo
         ...)                  # Argumentos adicionales
datos_csv <- read.csv("datos_csv.csv")
head(datos_csv)
##                     Nombre_Fondo            Tipo_Fondo Activos_Netos
## 1    American Century Intl. Disc Capital internacional         14.37
## 2 American Century Tax-Free Bond            Renta fija         10.73
## 3         American Century Ultra      Capital nacional         24.94
## 4              Artisan Small Cap      Capital nacional         16.92
## 5                Brown Cap Small      Capital nacional         35.73
## 6             DFA U.S. Micro Cap      Capital nacional         13.47
##   Rentabilidad_5_Años Ratio_Gastos Ranking_Morningstar
## 1               30.53         1.41              3-star
## 2                3.34         0.49              4-star
## 3               10.88         0.99              3-star
## 4               15.67         1.18              3-star
## 5               15.85         1.20              4-star
## 6               17.23         0.53              3-star

Desde un archivo de Excel

Para importar archivos de Excel (.xlsx o .xls) en R, se utiliza la función read_excel() del paquete readxl. A diferencia de read.table() o read.csv(), read_excel() está diseñada específicamente para leer archivos de Excel sin necesidad de convertirlos previamente a otro formato. Permite especificar el nombre del archivo y, opcionalmente, la hoja de cálculo que se desea importar mediante el argumento sheet. La función reconoce automáticamente si el archivo contiene un encabezado y no requiere indicar el tipo de separador, ya que Excel gestiona internamente la estructura de los datos.

Antes de utilizar read_excel(), es necesario cargar el paquete readxl con library(readxl).

# Cargar readxl
library(readxl)

datos_excel <- read_excel("datos_excel.xlsx", #Ruta del archivo
                          sheet = 1)    #Puedo elegir una hoja específica
head(datos_excel)
## # A tibble: 6 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 American Century In… Capital i…          14.4               30.5          1.41
## 2 American Century Ta… Renta fija          10.7                3.34         0.49
## 3 American Century Ul… Capital n…          24.9               10.9          0.99
## 4 Artisan Small Cap    Capital n…          16.9               15.7          1.18
## 5 Brown Cap Small      Capital n…          35.7               15.8          1.2 
## 6 DFA U.S. Micro Cap   Capital n…          13.5               17.2          0.53
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Tip: Algunas buenas prácticas son:

  • Guardar todos los archivos de datos en una carpeta específica del proyecto.

  • Usar nombres de archivos simples y descriptivos (sin espacios ni tildes).

  • Siempre verificar si los datos tienen encabezados (nombres de columnas).

  • Si al cargar un archivo los datos no se ven bien, revisar si el separador es correcto.

Exploramos la estructura de los datos

Antes de comenzar a trabajar con un conjunto de datos, es importante conocer cómo están organizados y cómo los está interpretando R. Esto nos permite asegurarnos de que las variables se hayan cargado correctamente y evitar errores en los análisis posteriores.

Existen varias funciones que nos ayudan a obtener esta información y vimos en el encuentro anterior:

  • head(): muestra las primeras filas del conjunto de datos.

  • dim(): informa la cantidad de filas y columnas (dimensiones).

  • names(): muestra los nombres de las variables (columnas).

Además de las funciones básicas, str() es una herramienta muy útil para obtener un resumen general de un conjunto de datos. Esta función muestra el tipo de objeto (por ejemplo, data.frame), la cantidad de filas (observaciones) y columnas (variables), y ofrece una descripción breve de cada variable, indicando su nombre, tipo de dato (numérico, texto, etc.) y los primeros valores registrados.

str(datos_excel)
## tibble [25 × 6] (S3: tbl_df/tbl/data.frame)
##  $ Nombre_Fondo       : chr [1:25] "American Century Intl. Disc" "American Century Tax-Free Bond" "American Century Ultra" "Artisan Small Cap" ...
##  $ Tipo_Fondo         : chr [1:25] "Capital internacional" "Renta fija" "Capital nacional" "Capital nacional" ...
##  $ Activos_Netos      : num [1:25] 14.4 10.7 24.9 16.9 35.7 ...
##  $ Rentabilidad_5_Años: num [1:25] 30.53 3.34 10.88 15.67 15.85 ...
##  $ Ratio_Gastos       : num [1:25] 1.41 0.49 0.99 1.18 1.2 0.53 0.89 0.9 0.89 0.45 ...
##  $ Ranking_Morningstar: chr [1:25] "3-star" "4-star" "3-star" "3-star" ...

El paquete skimr permite obtener un resumen estadístico detallado y rápido de un conjunto de datos. A diferencia de str(), que sólo muestra la estructura de las variables, skim() agrega información descriptiva adicional como medias, medianas, porcentajes de valores faltantes y pequeños histogramas que facilitan una primera exploración visual de las variables numéricas.

library(skimr)
skim(datos_excel)
Data summary
Name datos_excel
Number of rows 25
Number of columns 6
_______________________
Column type frequency:
character 3
numeric 3
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
Nombre_Fondo 0 1 9 30 0 25 0
Tipo_Fondo 0 1 10 21 0 3 0
Ranking_Morningstar 0 1 6 6 0 4 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
Activos_Netos 1 0.96 27.52 16.18 8.60 15.07 24.68 35.49 73.11 ▇▆▃▂▁
Rentabilidad_5_Años 0 1.00 16.50 10.39 2.37 13.41 15.46 17.23 51.10 ▃▇▂▁▁
Ratio_Gastos 0 1.00 0.94 0.39 0.16 0.62 1.05 1.25 1.41 ▂▃▃▂▇

Esta función es útil para tener una visión general del tipo de variables, la cantidad de datos faltantes y la distribución de las variables, antes de realizar análisis más avanzados.

Limpieza de datos

Visualización y tratamiento de valores faltantes

En muchos conjuntos de datos es común encontrarse con valores faltantes. En R, los valores faltantes se representan como NA (Not Available). Es importante identificarlos y decidir cómo tratarlos, ya que pueden influir en los resultados de los análisis.

Podemos detectar los valores faltantes con las siguientes funciones:

  • is.na(): indica para cada elemento si es faltante (TRUE) o no (FALSE).

  • sum(is.na()): cuenta la cantidad total de valores faltantes.

  • colSums(is.na()): muestra la cantidad de valores faltantes en cada variable (columna).

# Devuelve TRUE en cada posición donde encuentra un NA (uno por celda)
is.na(datos_excel)
##       Nombre_Fondo Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##  [1,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [2,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [3,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [4,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [5,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [6,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [7,]        FALSE      FALSE         FALSE               FALSE        FALSE
##  [8,]        FALSE      FALSE          TRUE               FALSE        FALSE
##  [9,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [10,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [11,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [12,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [13,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [14,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [15,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [16,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [17,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [18,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [19,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [20,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [21,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [22,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [23,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [24,]        FALSE      FALSE         FALSE               FALSE        FALSE
## [25,]        FALSE      FALSE         FALSE               FALSE        FALSE
##       Ranking_Morningstar
##  [1,]               FALSE
##  [2,]               FALSE
##  [3,]               FALSE
##  [4,]               FALSE
##  [5,]               FALSE
##  [6,]               FALSE
##  [7,]               FALSE
##  [8,]               FALSE
##  [9,]               FALSE
## [10,]               FALSE
## [11,]               FALSE
## [12,]               FALSE
## [13,]               FALSE
## [14,]               FALSE
## [15,]               FALSE
## [16,]               FALSE
## [17,]               FALSE
## [18,]               FALSE
## [19,]               FALSE
## [20,]               FALSE
## [21,]               FALSE
## [22,]               FALSE
## [23,]               FALSE
## [24,]               FALSE
## [25,]               FALSE
# Cuenta la cantidad total de NA en todo el conjunto de datos
sum(is.na(datos_excel))
## [1] 1
# Cuenta la cantidad de NA por cada variable (columna)
colSums(is.na(datos_excel))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   1                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0

Una vez identificados los NA, hay varias estrategias para tratarlos. La elección depende del tipo de análisis y del contexto de los datos. A continuación se presentan las opciones más habituales:

Opción Base R dplyr Uso
Omitir filas con NA na.omit() drop_na() Cuando las filas con valores faltantes son pocas y no afectan el análisis.
Reemplazar por un valor definido (por ejemplo, 0 o “Sin dato”) ifelse(is.na(), valor, valor_original) replace_na() Cuando tiene sentido completar el dato con una categoría o valor fijo que represente la ausencia.
Reemplazar por la media (en una variable numérica) mean() + ifelse() mean() + replace_na() ó if_else() Si puede asumirse que el dato faltante es similar al promedio de la muestra.
# Crear un nuevo objeto sin filas con NA
datos_sin_na <- na.omit(datos_excel)
#chequeamos si hay NA
colSums(is.na(datos_sin_na))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
# Reemplazar los NA por cero
datos_excel$Activos_Netos <- ifelse(is.na(datos_excel$Activos_Netos), 0, datos_excel$Activos_Netos)
#chequeamos si hay NA
colSums(is.na(datos_excel))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
#Vuelvo a cargar el excel original para recuperar el NA
datos_excel <- read_excel("datos_excel.xlsx", sheet = 1)   

# Reemplazar los NA de una variable por su media
media_AN <- mean(datos_excel$Activos_Netos, na.rm = TRUE)
datos_excel$Activos_Netos <- ifelse(is.na(datos_excel$Activos_Netos), media_AN, datos_excel$Activos_Netos)
#chequeamos si hay NA
colSums(is.na(datos_excel))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.4     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter()     masks stats::filter()
## ✖ dplyr::group_rows() masks kableExtra::group_rows()
## ✖ dplyr::lag()        masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
#Vuelvo a cargar el excel original para recuperar el NA
datos_excel <- read_excel("datos_excel.xlsx", sheet = 1)   

# Eliminar filas que tengan NA en cualquier variable
datos_sin_NA <- datos_excel %>% 
  drop_na()
#chequeamos si hay NA
colSums(is.na(datos_sin_NA))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
# Eliminar filas con NA solo en variables específicas
datos_sin_na_var <- datos_excel %>% 
  drop_na(Activos_Netos)
#chequeamos si hay NA
colSums(is.na(datos_sin_na_var))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
# Reemplazar NA por 0 en una variable numérica
datos_reem <- datos_excel %>%
  mutate(Activos_Netos = replace_na(Activos_Netos, 0))
#chequeamos si hay NA
colSums(is.na(datos_reem))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
# Calcular la media
media_AN <- mean(datos_excel$Activos_Netos, na.rm = TRUE)

# Reemplazar NA por la media
datos_reem_media <- datos_excel %>%
  mutate(Activos_Netos = replace_na(Activos_Netos, media_AN))
#chequeamos si hay NA
colSums(is.na(datos_reem_media))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0
# o también
datos_reem_media2 <- datos_excel %>%
  mutate(Activos_Netos = if_else(is.na(Activos_Netos), media_AN, Activos_Netos))
#chequeamos si hay NA
colSums(is.na(datos_reem_media2))
##        Nombre_Fondo          Tipo_Fondo       Activos_Netos Rentabilidad_5_Años 
##                   0                   0                   0                   0 
##        Ratio_Gastos Ranking_Morningstar 
##                   0                   0

Cuando la variable es cualitativa suele reemplazarse el NA por “Sin dato”. Esto puede hacerse con:

Transformación de datos con dplyr

El paquete dplyr es una herramienta muy utilizada para la manipulación de datos en R. Aunque las operaciones que permite realizar también se pueden hacer con la sintaxis base de R, dplyr ofrece una forma más clara, legible y eficiente de escribir el código. Su principal ventaja es que proporciona una gramática simple e intuitiva para trabajar con conjuntos de datos, especialmente con objetos del tipo data.frame o tibble. Además, muchas de sus funciones están optimizadas internamente en C++, lo que las hace más rápidas cuando se trabaja con grandes volúmenes de datos.

dplyr forma parte del conjunto de paquetes llamado tidyverse, que también incluye otros paquetes importantes como tidyr (para ordenar y transformar datos), ggplot2 (para visualización de datos), readr (para importar datos), stringr (para manejar cadenas de texto), entre otros.

Algunas de sus funciones más importantes son:

Función Descripción Ejemplo
select() Selecciona columnas (variables) del conjunto de datos.

datos %>%

select(variable1, variable2)
filter() Filtra filas (observaciones) que cumplen una condición.

datos %>%

filter(variable > 10)
arrange() Ordena las filas según una o más variables.

datos %>%

arrange(variable)
mutate() Crea nuevas variables o transforma variables existentes.

datos %>%

mutate(nueva_var = variable * 2)
summarise() Resume los datos calculando estadísticas (promedio, suma, etc.).

datos %>%

summarise(promedio = mean(variable))
group_by() Agrupa los datos según una o más variables, para aplicar resúmenes por grupo.

datos %>%

group_by(grupo) %>%

summarise(promedio = mean(variable))
distinct() Elimina filas duplicadas, conservando solo las únicas.

datos %>%

distinct(variable)
rename() Cambia el nombre de una o más variables.

datos %>%

rename(nuevo_nombre = nombre_original)
slice() Selecciona filas por su posición (por ejemplo, las primeras, las últimas o una fila específica).

datos %>%

slice(1:5)
drop_na() Elimina las filas con valores faltantes (NA).

datos %>%

drop_na()

Para comenzar a utilizarlo, cargamos el paquete tidyverse:

#Cargamos las librerías
library("tidyverse")

Ordenar datos

La función arrange permite ordear el data frame en función de una o más variables. Por defecto, ordena de forma ascendente (de menor a mayor o de A a Z).

Por una variable de manera ascendente

Ordenamos los datos por el Ratio de gastos de menor a mayor:

data_ord_rat <- datos_excel %>% 
  arrange(Ratio_Gastos)

head(data_ord_rat)
## # A tibble: 6 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 Vanguard Sht-Tm TE   Renta fija          15.7                2.37         0.16
## 2 Vanguard Sm Cp Idx   Capital n…          32.6               17.0          0.23
## 3 Vanguard Equity-Inc  Capital n…          24.4               13.4          0.29
## 4 Fidelity Sh-Term Bo… Renta fija           8.6                2.76         0.45
## 5 American Century Ta… Renta fija          10.7                3.34         0.49
## 6 DFA U.S. Micro Cap   Capital n…          13.5               17.2          0.53
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Por dos variables de manera descendente

Odenamos los datos primero por Ratio de gastos y luego por la Rentabilidad de los últimos 5 años, ambas de mayor a menor con la función desc:

data_ord_ratyrent <- datos_excel %>% 
  arrange(desc(Ratio_Gastos), desc(Rentabilidad_5_Años))

head(data_ord_ratyrent)
## # A tibble: 6 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 American Century In… Capital i…          14.4                30.5         1.41
## 2 RS Value A           Capital n…          26.3                23.7         1.36
## 3 Gabelli Asset AAA    Capital n…          49.8                16.7         1.36
## 4 Kalmar Gr Val Sm Cp  Capital n…          15.3                15.3         1.32
## 5 Marsico 21st Century Capital n…          17.5                15.2         1.31
## 6 Thornburg Value A    Capital n…          32.5                15.5         1.27
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Eliminar duplicados

Para eliminar duplicados usamos la función distinct:

data_sin_dup <- datos_excel %>% 
  distinct()

Renombrar variables

Usamos la función rename para renombrar las variables.

Renombramos la variable Ratio_Gastos a “Ratio de gastos”:

data_ren <- datos_excel %>% 
  rename(`Ratio de gastos` = Ratio_Gastos)

names(data_ren)
## [1] "Nombre_Fondo"        "Tipo_Fondo"          "Activos_Netos"      
## [4] "Rentabilidad_5_Años" "Ratio de gastos"     "Ranking_Morningstar"

Filtrar datos

Usamos la función filter para seleccionar filas según condiciones específicas.

Usando una condición sobre una variable cualitativa

Filtramos los fondos de Renta fija

data_rf <- datos_excel %>% 
  filter(Tipo_Fondo == "Renta fija")

head(data_rf)
## # A tibble: 5 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 American Century Ta… Renta fija          10.7                3.34         0.49
## 2 Fidelity Sh-Term Bo… Renta fija           8.6                2.76         0.45
## 3 PIMCO Emerg Mkts Bd… Renta fija          10.7               13.6          1.25
## 4 USAA Income          Renta fija          12.1                4.31         0.62
## 5 Vanguard Sht-Tm TE   Renta fija          15.7                2.37         0.16
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Usando una condición sobre una variable cuantitativa

Filtramos los fondos con un Ratio de gastos mayor a 1.

data_ra <- datos_excel %>% 
  filter(Ratio_Gastos > 1)

head(data_ra)
## # A tibble: 6 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 American Century In… Capital i…          14.4                30.5         1.41
## 2 Artisan Small Cap    Capital n…          16.9                15.7         1.18
## 3 Brown Cap Small      Capital n…          35.7                15.8         1.2 
## 4 Gabelli Asset AAA    Capital n…          49.8                16.7         1.36
## 5 Kalmar Gr Val Sm Cp  Capital n…          15.3                15.3         1.32
## 6 Marsico 21st Century Capital n…          17.5                15.2         1.31
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Usando dos condiciones

Filtramos los fondos de Renta fija con un Ratio de gastos mayor a 1.

data_rfyra <- datos_excel %>% 
  filter(Tipo_Fondo == "Renta fija" & Ratio_Gastos > 1)

head(data_rfyra)
## # A tibble: 1 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 PIMCO Emerg Mkts Bd… Renta fija          10.7                13.6         1.25
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Para eliminar datos faltantes

Una gran utilidad de esta función es que nos permite eliminar las filas con datos faltantes o NA que haya en alguna/s variable/s del conjunto de datos.

data_sin_na <- datos_excel %>% 
  filter(!is.na(Activos_Netos))

Eliminar valores faltantes

La función drop_na permite eliminar las filas que tengan NA en cualquier variable (en todo el conjunto de datos).

data_sin_na2 <- datos_excel %>% 
  drop_na() # si acá especificamos una varialbe, sólo se eliminan los NA de esa variable

Seleccionar columnas

Elegir columnas

La función select permite elegir qué columnas mantener en el conjunto de datos. Seleccionamos las columnas Tipo_Fondo y Activos_Netos:

data_2var <- datos_excel %>% 
  select(Tipo_Fondo, Activos_Netos)

names(data_2var)
## [1] "Tipo_Fondo"    "Activos_Netos"

Eliminar columnas

Eliminamos la columna de Tipo de Fondo:

data_sinTF <- datos_excel %>% 
  select(-Tipo_Fondo)

names(data_sinTF)
## [1] "Nombre_Fondo"        "Activos_Netos"       "Rentabilidad_5_Años"
## [4] "Ratio_Gastos"        "Ranking_Morningstar"

Reordenar columnas

Damos un nuevo orden a las columnas:

data_ordcol <- datos_excel %>% 
  select(Nombre_Fondo, Ranking_Morningstar, Rentabilidad_5_Años, Activos_Netos, Tipo_Fondo, Ratio_Gastos)

names(data_ordcol)
## [1] "Nombre_Fondo"        "Ranking_Morningstar" "Rentabilidad_5_Años"
## [4] "Activos_Netos"       "Tipo_Fondo"          "Ratio_Gastos"

Seleccionar filas

Con la función slice podemos podemos seleccionar filas específicas del conjunto de datos.

Seleccionar las primeras filas

primeros3 <- datos_excel %>% 
  slice(1:3) # seleccionamos las primeras 3 filas
primeros3
## # A tibble: 3 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 American Century In… Capital i…          14.4               30.5          1.41
## 2 American Century Ta… Renta fija          10.7                3.34         0.49
## 3 American Century Ul… Capital n…          24.9               10.9          0.99
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Seleccionar las últimas filas

ultimos3 <- datos_excel %>% 
  slice((n() - 2):n()) # seleccionamos las primeras 3 filas
ultimos3
## # A tibble: 3 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 Vanguard Sht-Tm TE   Renta fija          15.7                2.37         0.16
## 2 Vanguard Sm Cp Idx   Capital n…          32.6               17.0          0.23
## 3 Wasatch Sm Cp Growth Capital n…          35.4               14.0          1.19
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Seleccionar filas específicas

filas_2y5 <- datos_excel %>% 
  slice(c(2, 5)) # seleccionamos las filas 2 y 5
filas_2y5
## # A tibble: 2 × 6
##   Nombre_Fondo         Tipo_Fondo Activos_Netos Rentabilidad_5_Años Ratio_Gastos
##   <chr>                <chr>              <dbl>               <dbl>        <dbl>
## 1 American Century Ta… Renta fija          10.7                3.34         0.49
## 2 Brown Cap Small      Capital n…          35.7               15.8          1.2 
## # ℹ 1 more variable: Ranking_Morningstar <chr>

Crear y transformar variables

Con la función mutate podemos crear y transformar variables:

Crear una nueva variable

Categorizamos la variable Ratio de Gastos en Alto y Bajo:

data_cat <- datos_excel %>% 
  mutate(Ratio_cat = case_when(
    Ratio_Gastos >= 1 ~ "Alto",
    Ratio_Gastos < 1 ~ "Bajo"
  ))
#La nueva variable se agrega al final
names(data_cat)
## [1] "Nombre_Fondo"        "Tipo_Fondo"          "Activos_Netos"      
## [4] "Rentabilidad_5_Años" "Ratio_Gastos"        "Ranking_Morningstar"
## [7] "Ratio_cat"
#vemos sus valores
print(data_cat$Ratio_cat)
##  [1] "Alto" "Bajo" "Bajo" "Alto" "Alto" "Bajo" "Bajo" "Bajo" "Bajo" "Bajo"
## [11] "Alto" "Alto" "Alto" "Alto" "Alto" "Alto" "Alto" "Alto" "Bajo" "Alto"
## [21] "Bajo" "Bajo" "Bajo" "Bajo" "Alto"

Transformar una variable

A partir de la rentabilidad promedio anual de los últimos 5 años, podemos calcular la rentabilidad promedio mensual:

data_rentmens <- datos_excel %>% 
  mutate(Rentabilidad_5_Años = Rentabilidad_5_Años/12)
#La nueva variable se agrega al final
names(data_rentmens)
## [1] "Nombre_Fondo"        "Tipo_Fondo"          "Activos_Netos"      
## [4] "Rentabilidad_5_Años" "Ratio_Gastos"        "Ranking_Morningstar"
#vemos sus valores
print(data_rentmens$Rentabilidad_5_Años)
##  [1] 2.5441667 0.2783333 0.9066667 1.3058333 1.3208333 1.4358333 1.4991667
##  [8] 1.9550000 1.1250000 0.2300000 1.3916667 1.2758333 1.2633333 2.7250000
## [15] 0.7925000 1.1308333 1.9733333 4.2583333 1.4091667 1.2883333 0.3591667
## [22] 1.1175000 0.1975000 1.4175000 1.1650000

Construir variables complejas

Podemos construir una nueva variable compleja combinando categorías o valores de otras dos. Por ejemplo, podemos construir una variable a partir de Tipo_fondo y si la Rentabilidad_5_años es mayor a la media.

datos_otro <- datos_excel %>% 
  mutate(Variable_compleja=case_when(
    Tipo_Fondo == "Renta fija" & Rentabilidad_5_Años > mean(Rentabilidad_5_Años) ~ "Renta fija y rentabilidad mayor a la media",
    Tipo_Fondo == "Capital nacional" & Rentabilidad_5_Años > mean(Rentabilidad_5_Años) ~ "Capital nacional y rentabilidad mayor a la media",
    Tipo_Fondo == "Capital internacional" & Rentabilidad_5_Años > mean(Rentabilidad_5_Años) ~ "Capital internacional y rentabilidad mayor a la media",
    Tipo_Fondo == "Renta fija" & Rentabilidad_5_Años <= mean(Rentabilidad_5_Años) ~ "Renta fija y rentabilidad menor o igual a la media",
    Tipo_Fondo == "Capital nacional" & Rentabilidad_5_Años <= mean(Rentabilidad_5_Años) ~ "Capital nacional y rentabilidad menor o igual a la media",
    Tipo_Fondo == "Capital internacional" & Rentabilidad_5_Años <= mean(Rentabilidad_5_Años) ~ "Capital internacional y rentabilidad menor o igual a la media"
  ))

datos_otro$Variable_compleja
##  [1] "Capital internacional y rentabilidad mayor a la media"   
##  [2] "Renta fija y rentabilidad menor o igual a la media"      
##  [3] "Capital nacional y rentabilidad menor o igual a la media"
##  [4] "Capital nacional y rentabilidad menor o igual a la media"
##  [5] "Capital nacional y rentabilidad menor o igual a la media"
##  [6] "Capital nacional y rentabilidad mayor a la media"        
##  [7] "Capital nacional y rentabilidad mayor a la media"        
##  [8] "Capital internacional y rentabilidad mayor a la media"   
##  [9] "Capital nacional y rentabilidad menor o igual a la media"
## [10] "Renta fija y rentabilidad menor o igual a la media"      
## [11] "Capital nacional y rentabilidad mayor a la media"        
## [12] "Capital nacional y rentabilidad menor o igual a la media"
## [13] "Capital nacional y rentabilidad menor o igual a la media"
## [14] "Capital internacional y rentabilidad mayor a la media"   
## [15] "Capital nacional y rentabilidad menor o igual a la media"
## [16] "Renta fija y rentabilidad menor o igual a la media"      
## [17] "Capital nacional y rentabilidad mayor a la media"        
## [18] "Capital internacional y rentabilidad mayor a la media"   
## [19] "Capital nacional y rentabilidad mayor a la media"        
## [20] "Capital nacional y rentabilidad menor o igual a la media"
## [21] "Renta fija y rentabilidad menor o igual a la media"      
## [22] "Capital nacional y rentabilidad menor o igual a la media"
## [23] "Renta fija y rentabilidad menor o igual a la media"      
## [24] "Capital nacional y rentabilidad mayor a la media"        
## [25] "Capital nacional y rentabilidad menor o igual a la media"

Calcular medidas de resumen

Sobre todos los datos

Usando la función summarise podemos calcular estadísticas descriptivas, usando las siguientes funciones:

Medidas de tendencia central
  • mean(x) devuelve el promedio del argumento x.
  • median(x) devuelve la mediana del argumento x.
  • moda(x) devuelve la moda del argumento x.
Otras medidas de posición
  • quantile(x) devuelve el mínimo, el primer, segundo y tercer cuartil, y el máximo de x.
  • quantile(x, a) devuelve el cuantil a de x (a ∈ [0,1]).
Medidas de variabilidad
  • range(x) devuelve el valor mínimo y el valor máximo en x. Para calcular el rango aplicamos sobre esta función la función diff.
  • IQR(x) devuelve el rango intercuartil del argumento x.
  • var(x) devuelve la varianza del argumento x.
  • sd(x) devuelve el desvío estándar del argumento x.
  • Para calcular el coeficiente de variación, hacemos el cociente entre la desviación estándar y la media.

Calculamos las medidas de resumen de Activos Netos:

#Agregamos función para calcular la moda
moda <- function(x) {
  freqs <- table(x)  
  max_freq <- max(freqs)  
  if (sum(freqs == max_freq) == length(freqs)) {
    return("No hay moda")
  } else {
    return(as.numeric(names(freqs[freqs == max_freq])))
  }
}

medidas <- datos_sin_NA %>% 
  summarise(
    Media = mean(Activos_Netos),
    Mediana = median(Activos_Netos),
    Moda = moda(Activos_Netos),
    C1 = quantile(Activos_Netos, 0.25),
    C3 = quantile(Activos_Netos, 0.75),
    Rango = diff(range(Activos_Netos)),
    RIC = IQR(Activos_Netos),
    Varianza = var(Activos_Netos),
    Desvío = sd(Activos_Netos),
    CV = sd(Activos_Netos) / mean(Activos_Netos) * 100
  )

medidas
## # A tibble: 1 × 10
##   Media Mediana Moda           C1    C3 Rango   RIC Varianza Desvío    CV
##   <dbl>   <dbl> <chr>       <dbl> <dbl> <dbl> <dbl>    <dbl>  <dbl> <dbl>
## 1  27.5    24.7 No hay moda  15.1  35.5  64.5  20.4     262.   16.2  58.8

Por grupos

También podemos calcular las medidas por grupos usando la función group_by, por ejemplo por Tipo_Fondo:

medidas_grupo <- datos_sin_NA %>% 
  group_by(Tipo_Fondo) %>%
  summarise(
    Media = mean(Activos_Netos),
    Mediana = median(Activos_Netos),
    Moda = moda(Activos_Netos),
    C1 = quantile(Activos_Netos, 0.25),
    C3 = quantile(Activos_Netos, 0.75),
    Rango = diff(range(Activos_Netos)),
    RIC = IQR(Activos_Netos),
    Varianza = var(Activos_Netos),
    Desvío = sd(Activos_Netos),
    CV = sd(Activos_Netos) / mean(Activos_Netos) * 100
  )

medidas_grupo 
## # A tibble: 3 × 11
##   Tipo_Fondo   Media Mediana Moda     C1    C3 Rango   RIC Varianza Desvío    CV
##   <chr>        <dbl>   <dbl> <chr> <dbl> <dbl> <dbl> <dbl>    <dbl>  <dbl> <dbl>
## 1 Capital int…  32.0    27.9 No h…  21.1  40.9 39.5  19.8    404.    20.1   62.7
## 2 Capital nac…  31.7    29.4 No h…  21.2  36.9 59.6  15.7    238.    15.4   48.8
## 3 Renta fija    11.6    10.7 No h…  10.7  12.1  7.08  1.42     6.87   2.62  22.7

Análisis exploratorio de datos

El análisis exploratorio de datos (EDA) es una etapa fundamental que permite conocer la distribución, las características y posibles anomalías presentes en los datos antes de realizar un análisis más avanzado.

Resumen estadístico

La función summary() permite obtener un resumen estadístico de las variables numéricas y categóricas del conjunto de datos. Proporciona medidas como el mínimo, el primer cuartil, la mediana, la media, el tercer cuartil y el máximo para las variables numéricas; y el conteo de frecuencias para las categóricas.

summary(datos_sin_NA)
##  Nombre_Fondo        Tipo_Fondo        Activos_Netos   Rentabilidad_5_Años
##  Length:24          Length:24          Min.   : 8.60   Min.   : 2.37      
##  Class :character   Class :character   1st Qu.:15.07   1st Qu.:12.78      
##  Mode  :character   Mode  :character   Median :24.68   Median :15.38      
##                                        Mean   :27.52   Mean   :16.21      
##                                        3rd Qu.:35.49   3rd Qu.:17.07      
##                                        Max.   :73.11   Max.   :51.10      
##   Ratio_Gastos    Ranking_Morningstar
##  Min.   :0.1600   Length:24          
##  1st Qu.:0.5975   Class :character   
##  Median :1.1050   Mode  :character   
##  Mean   :0.9433                      
##  3rd Qu.:1.2550                      
##  Max.   :1.4100

Identificación de outliers

Los outliers o valores atípicos son observaciones que se alejan considerablemente del resto de los datos. Su detección es importante porque pueden distorsionar los análisis posteriores.

  • La función boxplot() permite visualizar la distribución de una variable y detectar posibles outliers. Los valores que aparecen fuera de los “bigotes” del boxplot son considerados potenciales atípicos.
# Boxplot para detectar valores atípicos
boxplot(datos_sin_NA$Activos_Netos)

boxplot(datos_sin_NA$Rentabilidad_5_Años)

  • La función plot() permite generar un gráfico de dispersión para observar la relación entre dos variables y detectar posibles patrones o valores atípicos.
# Gráfico de dispersión para observar patrones
plot(datos_sin_NA$Activos_Netos, datos_sin_NA$Rentabilidad_5_Años)

¿Cómo se pueden tratar los outliers?

Una vez identificados, existen varias formas de tratar los outliers, dependiendo del contexto y los objetivos del análisis. Los outliers pueden eliminarse si se considera que distorsionan los resultados y no son representativos, reemplazarse por un valor más representativo como la mediana, o transformarse la variable para reducir la influencia de los valores extremos. También es posible mantenerlos si representan casos válidos y relevantes para el análisis. Es fundamental justificar cualquier decisión sobre el tratamiento de outliers, considerando siempre el contexto del estudio y los objetivos del análisis. A continuación, veremos cómo realizar estos tratamientos en R.

1. Eliminar los outliers

Una forma simple de eliminar outliers es filtrar las observaciones que están dentro de un rango determinado. Por ejemplo, se pueden eliminar los valores que se encuentran fuera del rango intercuartílico (IQR).

# Calcular los cuartiles y el rango intercuartílico (IQR)
Q1 <- quantile(datos_sin_NA$Activos_Netos, 0.25)
Q3 <- quantile(datos_sin_NA$Activos_Netos, 0.75)
IQR <- Q3 - Q1

# Definir los límites inferior y superior
limite_inferior <- Q1 - 1.5 * IQR
limite_superior <- Q3 + 1.5 * IQR

# Filtrar los datos que están dentro de los límites (sin outliers)
datos_sin_outliers <- datos_sin_NA %>%
  filter(Activos_Netos >= limite_inferior & Activos_Netos <= limite_superior)

boxplot(datos_sin_outliers$Activos_Netos)

2. Reemplazar los outliers

Otra opción es reemplazar los valores atípicos por un valor más representativo, como la mediana o la media.

# Calcular la mediana
mediana_AN <- median(datos_sin_NA$Activos_Netos, na.rm = TRUE)

# Reemplazar los valores fuera de los límites por la mediana
datos_reemplazo_outliers <- datos_sin_NA %>%
  mutate(Activos_Netos = ifelse(Activos_Netos < limite_inferior | Activos_Netos > limite_superior,
                                 mediana_AN,
                                 Activos_Netos))

boxplot(datos_reemplazo_outliers$Activos_Netos)

3. Transformar las variables

Otra estrategia es aplicar una transformación que reduzca la influencia de los valores extremos, como la transformación logarítmica o raíz cuadrada.

# Transformación logarítmica (agregando 1 si hay ceros)
datos_transformados <- datos_sin_NA %>%
  mutate(Activos_Netos_log = log(Activos_Netos))
boxplot(datos_transformados$Activos_Netos_log)

# Transformación raíz cuadrada
datos_transformados <- datos_sin_NA %>%
  mutate(Activos_Netos_sqrt = sqrt(Activos_Netos))
boxplot(datos_transformados$Activos_Netos_sqrt)

Estas transformaciones suavizan la distribución de la variable y disminuyen el efecto de los valores atípicos, sin eliminar datos.