<- read.csv("Snail_feeding.csv") Snail_feeding
Importing Data
Antes de poder ejecutar análisis de datos o crear gráficos en R, debemos importar esos datos a R. Preparar y limpiar los datos para el análisis es esencial y a menudo requiere más tiempo que los propios análisis estadísticos. Es inusual que los datos sin procesar estén en el formato correcto y sin errores. La limpieza de datos es el proceso de identificar y corregir cualquier problema para que los datos puedan ser analizados fácilmente.
Importar datos es un desafío importante para los principiantes. Este módulo brindará instrucciones para una de las formas más comunes de importar datos, así como algunos desafíos que puedes enfrentar y cómo superarlos. Algunos de estos problemas se pueden evitar siguiendo buenas prácticas de entrada y gestión de datos (lee primero Entrada de datos para obtener ayuda con esto).
Importar datos como un marco de datos
Recomendamos ingresar los datos en un programa de hoja de cálculo (por ejemplo, Excel) y guardar esos datos como un archivo de valores separados por comas (.csv). Estos se pueden leer fácilmente en R y compartir entre usuarios con diferentes programas de hojas de cálculo.
En este módulo, vamos a utilizar un conjunto de datos de muestra sobre el comportamiento de alimentación de un caracol marino para demostrar cómo importar los datos y los problemas más comunes que surgen al importar y limpiar datos en R.
Primero, guarda el archivo de datos, Snail_feeding.csv, en tu directorio de trabajo. Consulta Introducción a R para obtener ayuda sobre cómo configurar el directorio de trabajo.
Segundo, importa el archivo de datos a un marco de datos llamado Snail_feeding utilizando la función read.csv
.
Limpieza de data frames
Cuando utilizas read.csv
, R utiliza varios argumentos por defecto que se pueden modificar para asegurar que tus datos se importen con menos errores. Echa un vistazo al archivo de ayuda dentro de R (escribiendo ?read.csv
) para familiarizarte con algunos de estos argumentos.
Los que son particularmente útiles son:
header = T
- al especificar esto como T (es decir, TRUE), asegurarás que los valores en la primera fila de tus datos se traten como nombres de variables.
strip.white = T
- esto eliminará los espacios en blanco al final y al principio de los factores. Este es un error común al escribir los datos (por ejemplo, “males” vs “males_”). Si lo establecemos como TRUE, ambos se convertirán en “males”. De lo contrario, R considerará que hay dos niveles diferentes.
na.strings = ""
- esto asegurará que las celdas vacías se reemplacen por NA (la forma en que R registra los datos faltantes). De manera molesta, R importa valores faltantes dentro de caracteres/factores como el valor ““. Usando na.strings = ""
, se insertarán NAs en su lugar. Además, si has codificado valores faltantes como algo distinto a un espacio en blanco, puedes definir ese valor faltante usando este argumento (por ejemplo, na.strings = c("", "-", "*")
).
Al combinar todos estos en la función read.csv
, obtendremos un marco de datos más limpio.
<- read.csv("Snail_feeding.csv", header = T, strip.white = T, na.strings = "") Snail_feeding
Verificación de los datos
Si algo es un carácter cuando debería ser numérico, es posible que veas mensajes como “‘x’ must be numeric” o “non-numeric argument to binary operator”. De manera similar, si algo es un factor cuando debería ser un carácter, algunas operaciones con caracteres podrían fallar. Para evitar algunos de estos problemas, verifica tus datos utilizando str
y summary
antes de realizar análisis.
str
te permite verificar la estructura de tus datos y asegurarte de que tus variables tengan el tipo correcto (es decir, numérico, caracteres, enteros o factores). Consulta Tipos de datos y estructura para obtener explicaciones sobre estos diferentes tipos.
str(Snail_feeding)
## 'data.frame': 768 obs. of 12 variables:
## $ Snail.ID: int 1 1 1 1 1 1 1 1 1 1 ...
## $ Sex : chr "male" "male" "males" "male" ...
## $ Size : chr "small" "small" "small" "small" ...
## $ Feeding : logi FALSE FALSE FALSE FALSE FALSE TRUE ...
## $ Distance: chr "0.17" "0.87" "0.22" "0.13" ...
## $ Depth : num 1.66 1.26 1.43 1.46 1.21 1.56 1.62 162 1.96 1.93 ...
## $ Temp : int 21 21 18 19 21 21 20 20 19 19 ...
## $ X : logi NA NA NA NA NA NA ...
## $ X.1 : logi NA NA NA NA NA NA ...
## $ X.2 : logi NA NA NA NA NA NA ...
## $ X.3 : logi NA NA NA NA NA NA ...
## $ X.4 : logi NA NA NA NA NA NA ...
summary
te permite ver estadísticas básicas para cada una de tus variables y se puede utilizar para identificar errores obvios (es decir, máximos o mínimos extremos en relación a la media o mediana, o grupos adicionales dentro de un vector categórico).
summary(Snail_feeding)
## Snail.ID Sex Size Feeding
## Min. : 1.00 Length:768 Length:768 Mode :logical
## 1st Qu.: 4.75 Class :character Class :character FALSE:502
## Median : 8.50 Mode :character Mode :character TRUE :266
## Mean : 8.50
## 3rd Qu.:12.25
## Max. :16.00
##
## Distance Depth Temp X
## Length:768 Min. : 1.000 Min. :18.00 Mode:logical
## Class :character 1st Qu.: 1.260 1st Qu.:19.00 NA's:768
## Mode :character Median : 1.510 Median :19.00
## Mean : 1.716 Mean :19.49
## 3rd Qu.: 1.760 3rd Qu.:20.00
## Max. :162.000 Max. :21.00
## NA's :6
## X.1 X.2 X.3 X.4
## Mode:logical Mode:logical Mode:logical Mode:logical
## NA's:768 NA's:768 NA's:768 NA's:768
##
##
##
##
##
Ten en cuenta que para el factor de sexo, errores en la entrada de datos resultaron en cinco niveles (female, female s, male, Male y males) cuando debería haber solo dos. Ver a continuación la solución.
Problemas comunes al importar datos
No obtienes el número de columnas o filas que esperas
Si ves un montón de columnas adicionales (X, X.1, X.2, X.3, etc.) o filas en tu marco de datos llenas de NA, es probable que se haya ingresado un carácter adicional (probablemente un espacio en blanco o una tabulación) en celdas más allá de tus datos reales en Excel. Este problema se puede evitar durante la entrada de datos eliminando todos los colores/formatos y vaciando columnas/filas excepto las necesarias.
Si el problema persiste, podemos abordarlo en R mediante la indexación dentro de corchetes cuadrados dataframe[fila, columna]
. Por ejemplo, el siguiente código reemplazará el marco de datos en este ejemplo con uno que solo incluye las primeras 7 columnas y elimina las 5 no deseadas (X, X.1, X.2, X.3, etc.).
<- Snail_feeding[, 1:7] Snail_feeding
El paquete dplyr tiene varias funciones muy útiles para subconjuntar filas y columnas. Consulta Subsetting data para obtener ayuda con esto.
Si tienes muchas columnas y no quieres contarlas, puedes usar lógica (&, or, ==, >, < , !=) para eliminar las filas y columnas no deseadas. No queremos eliminar todos los valores NA, solo las filas y columnas adicionales que estén completamente llenas de NAs. Estas tienen la propiedad de que el número de NAs es igual al número de filas en una columna dada (o número de columnas en una fila dada).
Hacemos esto seleccionando las columnas de nuestro data frame donde la suma de columnas, colSums
, de todos los NAs, >is.na
, en nuestro data frame no sea igual, !=
, al número de filas, nrow
, de nuestro data frame. Puedes usar la misma lógica para hacer esto con las filas también.
# Selects rows that are not entirely NA
<- Snail_feeding[, colSums(is.na(Snail_feeding)) != nrow(Snail_feeding)]
Snail_feeding # Select columns that are not entirely NA
<- Snail_feeding[rowSums(is.na(Snail_feeding)) != ncol(Snail_feeding), ] Snail_feeding
Las columnas no son del tipo de datos que esperas
Caracteres como factores Cuando se importan marcos de datos en R, los caracteres se convierten automáticamente en factores. Esto tiene mucho sentido para el trabajo estadístico; es más probable que queramos trabajar con factores (definidos anteriormente) que con caracteres. Los factores son fantásticos cuando se hace análisis estadístico y se explora realmente los datos. Sin embargo, antes de eso, cuando se leen, limpian, solucionan problemas, fusionan y manipulan los datos en general, los factores son un dolor de cabeza total.
Puedes usar el argumento stringsAsFactors=FALSE
al importar los datos para evitar la conversión automática a factores o puedes usar as.character
para convertir vectores individuales en caracteres.
Consejo: Utiliza factores lo más tarde posible en el proceso de análisis. Configura stringsAsFactors=FALSE
al importar tus datos y, cuando necesites factores en algún lugar dentro de tu script, convierte los datos a un factor.
Factores como enteros En este marco de datos, el ID de caracol es un entero cuando debería ser un factor o un carácter. Esto se debe a que en la hoja de datos original, el ID de caracol se codificó utilizando números. Este es un problema común y es fácil de solucionar. Simplemente usa as.factor()
o as.character()
, y luego class()
para verificar que nuestra conversión haya funcionado. Recuerda usar $
para acceder al vector desde dentro del marco de datos.
$Snail <- as.factor(Snail_feeding$Snail)
Snail_feedingclass(Snail_feeding$Snail)
## [1] "factor"
Números como caracteres (factores) Debido a la coerción automática en R, cualquier dígito no numérico dentro de una variable numérica resultará en que toda la variable se convierta en un carácter (R lo importa como factores). En este ejemplo, la variable “Distance” se ha importado como un factor con 768 niveles, cuando en realidad debería ser una variable numérica. Esto indica que hay un error tipográfico en alguna parte del vector de distancias. Estos errores tipográficos son comunes (por ejemplo, usar accidentalmente una coma en lugar de un punto decimal al ingresar decimales), pero un poco más difíciles de resolver.
Con un conjunto de datos pequeño, lo más rápido es regresar a los datos originales y encontrar el error. Una vez corregido, vuelves a importar y la variable debería ser numérica.
Con un conjunto de datos más grande, surge el problema de tener que encontrar los errores tipográficos. Desafortunadamente, no podemos convertir directamente nuestros datos de un vector de tipo factor a numérico. Esto se debe al atributo “levels” (consultar Tipos de datos y estructura). Si intentas convertir un factor directamente en una variable numérica, los valores se convierten en un número que corresponde al número de niveles (1:n, ordenados alfabéticamente o de forma ascendente) en lugar del valor real.
Por lo tanto, primero debemos convertirlo a carácter y luego a numérico. Al convertirlo a numérico, obtendrás un mensaje de advertencia “NAs introduced by coercion”. Esto se debe a que los valores no numéricos (es decir, nuestros errores tipográficos) no se pueden convertir a numéricos y se reemplazan por NA.
Podemos aprovechar esto, utilizando is.na
en combinación con which
para identificar dónde están los errores tipográficos o los valores faltantes dentro del vector.
$Distance <- as.character(Snail_feeding$Distance)
Snail_feeding$Distance <- as.numeric(Snail_feeding$Distance)
Snail_feeding## Warning: NAs introducidos por coerción
which(is.na(Snail_feeding$Distance))
## [1] 682 755
Esto nos indica que algo extraño sucedió en las filas 682 y 755. Ahora que hemos identificado dónde está el problema, es fácil reemplazar los valores en nuestro marco de datos con los valores correctos (vuelve a tu hoja de datos original). Puedes corregir el error en el conjunto de datos y volver a importarlo, o reemplazar los valores en R utilizando índices dentro de corchetes y asignando el nuevo valor con <-
. Usa which(is.na())
para verificar si tu corrección funcionó.
682, "Distance"] <- 0.356452
Snail_feeding[755, "Distance"] <- 0.42336
Snail_feeding[
which(is.na(Snail_feeding$Distance))
## integer(0)
Tienes más niveles de variables de los esperados
Uno de los pasos más importantes en cualquier análisis de datos o tarea de procesamiento es verificar que los valores de tus datos sean correctos. Por ejemplo, se esperaría que una variable llamada “Sexo” tenga solo dos niveles. Sin embargo, en nuestro marco de datos tiene cinco niveles (ver str
y summary
arriba).
Puedes verificar los niveles de un factor o los valores únicos de caracteres con levels
(solo para factores) o unique
(para caracteres y factores).
levels(Snail_feeding$Sex)
## NULL
unique(Snail_feeding$Sex)
## [1] "male" "males" "Male" "female" "female s"
Hay varios errores tipográficos que podemos corregir utilizando unique
y which
, así como los operadores lógicos ==
(igual) y |
(o) para identificar y reemplazar los errores tipográficos.
Para reemplazar cualquier valor que sea “males” o “Male” con “male”, usaríamos:
$Sex[which(Snail_feeding$Sex == "males" | Snail_feeding$Sex == "Male")] <- "male" Snail_feeding
Para reemplazar cualquier valor que sea “female s” con “female”, usaríamos:
$Sex[which(Snail_feeding$Sex == "female s")] <- "female" Snail_feeding
Verifica que funcione usando unique
, pero también observa lo que sucede cuando verificas los levels
(niveles).
unique(Snail_feeding$Sex)
## [1] "male" "female"
levels(Snail_feeding$Sex)
## NULL
Cuando usamos unique
para verificar nuestras categorías, solo aparecen “male” y “female”, sin embargo, cuando observamos los niveles, todavía tenemos los cinco niveles diferentes, incluyendo los errores tipográficos. Esto se debe al comportamiento de los factores. Una vez que se han definido los niveles, seguirán existiendo independientemente de si están incluidos en alguna muestra. Dado que nuestros niveles adicionales eran errores tipográficos y no niveles reales, debemos eliminarlos de los atributos.
factor
eliminará los niveles adicionales de un vector.
$Sex <- factor(Snail_feeding$Sex)
Snail_feedinglevels(Snail_feeding$Sex)
## [1] "female" "male"
Errores numéricos
Usar summary
anteriormente es una herramienta útil para verificar posibles errores tipográficos en nuestras variables numéricas. Compara el valor máximo o mínimo con la mediana de cada variable numérica. Si alguno de los valores es una orden de magnitud mayor o menor que la mediana, podría ser un error tipográfico. Por ejemplo, observa la profundidad máxima, parece que se ha olvidado el punto decimal.
Nuevamente, podemos utilizar operadores lógicos e indexación para identificar posibles errores numéricos. Dado que todos los valores de nuestra variable de profundidad parecen estar entre 1 y 2 (según los rangos intercuartiles de summary), buscaremos filas con una profundidad mayor a 2.
which(Snail_feeding$Depth > 2), ]
Snail_feeding[## Snail.ID Sex Size Feeding Distance Depth Temp Snail
## 8 1 male small TRUE 0.6 162 20 1
Solo hay 1 fila. Después de confirmar con nuestros datos originales que esto es, de hecho, un error tipográfico, lo reemplazaremos con el valor real. Seleccionando la fila y la columna, reemplazamos el valor 162 con 1.62.
which(Snail_feeding$Depth > 2), 6] <- 1.62 Snail_feeding[
¿Por qué hacer esto en R?
Puede que te preguntes por qué molestarse en corregir esto en R. ¿Por qué no ir directamente al archivo .csv y corregir todos los problemas? Por lo general, está bien hacer esto si sabes que el problema es un error tipográfico, etc. Sin embargo, para mantener la integridad de los datos, es importante tener un registro de cada cambio que se haya realizado en tu conjunto de datos original. Al realizar todas las manipulaciones y correcciones en R, también estás guardando un registro de todos los cambios que se están produciendo en tus datos.
Además, es posible que desees comenzar a explorar los datos antes de haber recopilado todo el conjunto de datos. Si configuras un script que verifique todas estas cosas antes de crear gráficos y ejecutar análisis, es rápido volver a ejecutar el script en los datos completos una vez que los tengas todos. El script actúa como un recordatorio de todas las cosas que debes verificar y es mejor para detectar errores tipográficos que tú en una hoja de cálculo enorme.
La verificación final
Finalmente, una vez que hayas verificado y corregido todos los problemas en tus datos, vuelve a ejecutar str
y summary
. De hecho, es una buena idea ejecutar estas funciones regularmente durante la limpieza de datos para estar al tanto de cualquier cambio que realices.
str(Snail_feeding)
## 'data.frame': 768 obs. of 8 variables:
## $ Snail.ID: int 1 1 1 1 1 1 1 1 1 1 ...
## $ Sex : Factor w/ 2 levels "female","male": 2 2 2 2 2 2 2 2 2 2 ...
## $ Size : chr "small" "small" "small" "small" ...
## $ Feeding : logi FALSE FALSE FALSE FALSE FALSE TRUE ...
## $ Distance: num 0.17 0.87 0.22 0.13 0.36 0.84 0.69 0.6 0.85 0.59 ...
## $ Depth : num 1.66 1.26 1.43 1.46 1.21 1.56 1.62 1.62 1.96 1.93 ...
## $ Temp : int 21 21 18 19 21 21 20 20 19 19 ...
## $ Snail : Factor w/ 16 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
summary(Snail_feeding)
## Snail.ID Sex Size Feeding
## Min. : 1.00 female:384 Length:768 Mode :logical
## 1st Qu.: 4.75 male :384 Class :character FALSE:502
## Median : 8.50 Mode :character TRUE :266
## Mean : 8.50
## 3rd Qu.:12.25
## Max. :16.00
##
## Distance Depth Temp Snail
## Min. :0.0000 Min. :1.000 Min. :18.00 1 : 48
## 1st Qu.:0.2775 1st Qu.:1.260 1st Qu.:19.00 2 : 48
## Median :0.5100 Median :1.510 Median :19.00 3 : 48
## Mean :0.5120 Mean :1.507 Mean :19.49 4 : 48
## 3rd Qu.:0.7500 3rd Qu.:1.760 3rd Qu.:20.00 5 : 48
## Max. :1.0000 Max. :2.000 Max. :21.00 6 : 48
## NA's :6 (Other):480
Más ayuda
Introducción a la limpieza de datos en R por de Jonge y van de Loo
R-bloggers - errores comunes en la importación de tablas
Autor: Keryn Bain - 2016