Accediendo al conjunto de datos

En esta demo usaremos el conjunto de datos gapminder disponible en el paquete con el mismo nombre. Usaremos la función install.packages() para instalar el paquete y luego la función library() para cargarlo a R.

## install.packages("gapminder")
library(gapminder)

Una vez instalado y cargado el paquete, podemos acceder al conjunto de datos gapminder y su documentación usando las funciones data() y help().

data("gapminder")
## help(gapminder)

La última línea de código deberá mostrar la documentación en el panel de ayuda si estas desde RStudio. Si estas desde la consola de R, se deberá abrir una página web en tu navegador predeterminado.

Según la descripción de la documentación, este conjunto de datos contiene información sobre la esperanza de vida, el PIB (producto interno bruto) per cápita y la población por país. Éste es un data frame con 1704 observaciones (renglones) y 6 variables (columnas). La siguiente tabla contiene una descripción de las variables que componen al conjunto de datos. Esta fue extraida directamente de la documentación.

Descripción del contenido del conjunto de datos gapminder.
Variable Descripción
country país: factor con 142 categorías
continent continente: factor con 5 categorías
year año: de 1952 a 2007 en incrementos de 5 años
lifeExp esperanza de vida al nacer, en años
pop población
gpdPercap PIB per cápita (dólares americanos)

Visualización del conjunto

Visualicemos ahora el conjunto de datos. Para esto podemos usar las funciones str(), summary(), y/o head(). Usemos las tres para ver que información proporciona cada una de ellas.

La función str()

The función str() muestra la estructura interna del objeto que le pasemos. En este caso, la estructura de gapminder

str(gapminder)
## tibble [1,704 × 6] (S3: tbl_df/tbl/data.frame)
##  $ country  : Factor w/ 142 levels "Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ continent: Factor w/ 5 levels "Africa","Americas",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ year     : int [1:1704] 1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
##  $ lifeExp  : num [1:1704] 28.8 30.3 32 34 36.1 ...
##  $ pop      : int [1:1704] 8425333 9240934 10267083 11537966 13079460 14880372 12881816 13867957 16317921 22227415 ...
##  $ gdpPercap: num [1:1704] 779 821 853 836 740 ...

Al inicio nos dice que gapminder es un tibble y no un data.frame. Los tibbles son versiones modificadas de los data frames. Son especialmente útiles cuando tenemos un conjunto de datos enorme. Por ahora, imaginemos que son lo mismo.

A un lado de la palabra tibble, nos muestra [1,704 x 6]. Esto nos indica el tamaño (o dimensión) del conjunto de datos. Este conjunto tiene 1704 observaciones y 6 variables. Puedes obtener el mismo resultado ejecutando dim(gapminder).

A partir de la segunda línea, nos muestra una descripción breve de cada variable. El signo $ indica variable. La primera variable es country que es de tipo factor con 142 categorías que empiezan con “Afghanistan”. Los valores después de : indican los valores que son almacenados. Al ser ésta una variable de tipo factor, las categorías son alamacenadas como números (con etiqueta). En este caso, los 1’s indicarían la categoría “Afghanistan”. Los tres puntos (…) indican que la lista de valores continua.

De manera similar, podemos extraer información de las otras variables, como, por ejemplo, year que es una variable entera (int) con 1704 valores. Sus primeros valores son 1952, 1957, 1692, ….

Por último, de aquí podemos deducir el tipo de variable que es cada una. country y continent son variables categóricas (factor en R) y las restantes son variables numéricas (numeric o integer en R).

La función summary()

Otra función que nos ayuda a visualizar el conjunto de datos de manera resumida es summary() (resumen en inglés). Veamos que nos dice

summary(gapminder)
##         country        continent        year         lifeExp     
##  Afghanistan:  12   Africa  :624   Min.   :1952   Min.   :23.60  
##  Albania    :  12   Americas:300   1st Qu.:1966   1st Qu.:48.20  
##  Algeria    :  12   Asia    :396   Median :1980   Median :60.71  
##  Angola     :  12   Europe  :360   Mean   :1980   Mean   :59.47  
##  Argentina  :  12   Oceania : 24   3rd Qu.:1993   3rd Qu.:70.85  
##  Australia  :  12                  Max.   :2007   Max.   :82.60  
##  (Other)    :1632                                                
##       pop              gdpPercap       
##  Min.   :6.001e+04   Min.   :   241.2  
##  1st Qu.:2.794e+06   1st Qu.:  1202.1  
##  Median :7.024e+06   Median :  3531.8  
##  Mean   :2.960e+07   Mean   :  7215.3  
##  3rd Qu.:1.959e+07   3rd Qu.:  9325.5  
##  Max.   :1.319e+09   Max.   :113523.1  
## 

En el caso se las variables categóricas, como country y continent, nos muestra las diferentes categorías y un conteo de cada una de éstas. Esto es, en la variable continent, la categoría Africa aparece 624 veces, Americas 300, Asia 396, Europe 360 y Oceania 24 veces.

Para las variables numéricas como year, lifeExp, pop y gdpPercap, summary() nos muestra la media, los tres cuartiles y los valores mínimo y máximo. Por ejemplo, el PIB per capita (gpdPercap) mínimo registrado es 241.2 y el máximo registrado es 113523.1.

No te asustes con los valores que aparecen en la variable pop, es notación científica, o sea, 6.001e+04 es lo mismo que \(6.001\times10^4=60,010\) y 1.319e+09 es igual a \(1.319\times10^9=1,319,000,000\).

La función head()

Por último, veamos la función head(). Ésta nos muestra la primera porción del conjunto de datos. Podemos especificarle cuantas observaciones queremos visualizar con el argumento n.

Nota: tail() hace lo mismo pero con la última porción del conjunto de datos.

head(gapminder, n = 8)

En el caso en el que el conjuto de datos sea un tibble nos mostrará, abajo del nombre de la variable, el tipo de variable. Por ejemplo, lifeExp es de tipo <dbl>, que es “sinónimo” de numeric. Debajo de country aparece <fctr> lo que significa factor. Seguido de esto, aparecerán las observaciones. La primera observación es (Afganistan, Asia, 1952, 28.801, 8425333, 779.4453), que se puede leer como: en el país de Afganistan del continente de Asia en el año 1952, la esperanza de vida era de 28.801 años, la población de 8,425,333 habitantes con un PIB per cápita de 779.4453 dólares americanos.

Limpieza del conjunto

Cuando se quiere usar un conjunto de datos para hacer cualquier tipo de análisis estadístico el primer paso casi siempre es limpiar el conjunto de datos. Es decir, buscar los datos faltantes (NAs o cadenas vacías "") o datos incorrectos. También es común darle el formato adecuado a las variables.

La función is.na()

Empecemos por buscar si hay datos faltantes o valores NA. La función is.na() evalua los elementos de un objeto en R, por ejemplo, un data frame o tibble, y regresa TRUE o FALSE si el elemento es NA o no, respectivamente. Por ejemplo,

x = c(1,2,3,NA,4,5,NA)
is.na(x)
## [1] FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE

La función regresó TRUE en las posiciones 4 y 7 del vector y FALSE para las restantes pues en en el vector x, los elementos 4 y 7 son NAs.

En nuestro caso, solo nos interesa saber si hay algún (any en inglés) valor NA en gapminder, por lo que combinando estas dos funciones podríamos contestar a esta pregunta

any(is.na(gapminder)) # leelo como ¿algún valor es NA en gapminder?
## [1] FALSE

¡Que bien! No hay ningún NA. Peeero, este no es el único tipo de valor faltante. Veamos el segundo, las cadenas vacías.

La función which()

Para comparar dos valores (numéricos o caracteres) específicos debemos usar operadores lógicos: == para la igualdad, > , <, >=, <=, o != para la diferencia. Veamos como funciona ==

x = c("A","B","C","","","D")
x == ""
## [1] FALSE FALSE FALSE  TRUE  TRUE FALSE

== comparará uno a uno los valores de x con la cadena vacía "" y regresará TRUE si son idénticas o FALSE si no lo son. En este caso, regresa TRUE en la posición 4 y 5, que coinciden perfectamente con la posición de las cadenas vacías en x, y regresa FALSE en las posiciones restantes pues no son cadenas vacías.

De nuevo, no estamos interesados en saber las posiciones de las cadenas vacías, por ahora, por lo que sería suficiente con usar any() en combinación con los operadores lógicos para saber si hay alguna cadena vacía de gapminder

any(gapminder == "") # Leelo como ¿Hay algún valor en gapminder igual a "")
## [1] FALSE

¡Fiuuuu! Tampoco hay cadenas vacías. Peeeero, si las hubiera, nos interesaría saber la posiciones de tales cadenas vacías. Aquí es donde entra la función which()

x = c("A","B","C","","","D")
which(x == "")
## [1] 4 5

Esta nos regresa la posición de las cadenas vacías en x, justamente la 4ta y 5ta. ¿Qué pasará si lo aplicamos a nuestro conjunto de datos?

which(gapminder == "")
## integer(0)

¿No esperabas que regresara alguna posición o sí? Al no haber cadenas vacías en gapminder, ésta regresa integer(0), o sea, no hay posición que regresar.

La función unique()

Ok, parece no haber datos faltantes, y a juzgar por el resumen que obtuvimos previamente, no parece haber datos incorrectos.

summary(gapminder)
##         country        continent        year         lifeExp     
##  Afghanistan:  12   Africa  :624   Min.   :1952   Min.   :23.60  
##  Albania    :  12   Americas:300   1st Qu.:1966   1st Qu.:48.20  
##  Algeria    :  12   Asia    :396   Median :1980   Median :60.71  
##  Angola     :  12   Europe  :360   Mean   :1980   Mean   :59.47  
##  Argentina  :  12   Oceania : 24   3rd Qu.:1993   3rd Qu.:70.85  
##  Australia  :  12                  Max.   :2007   Max.   :82.60  
##  (Other)    :1632                                                
##       pop              gdpPercap       
##  Min.   :6.001e+04   Min.   :   241.2  
##  1st Qu.:2.794e+06   1st Qu.:  1202.1  
##  Median :7.024e+06   Median :  3531.8  
##  Mean   :2.960e+07   Mean   :  7215.3  
##  3rd Qu.:1.959e+07   3rd Qu.:  9325.5  
##  Max.   :1.319e+09   Max.   :113523.1  
## 

Tal vez te preguntes, ¿cómo puedo saber si hay registros incorrectos? La verdad es que no puedes, a menos que sean muy evidentes. Si, por ejemplo, en el resumen del conjunto de datos, en la variable pop el registro más pequeño, o sea el mínimo, es -45, evidentemente hay un registro incorrecto pues no puede haber un país con población negativa.

¿Qué hay de las variables categóricas? Tal vez alguna categoría esté mal escrita. Veamos las categorías distintas o únicas de cada variable categórica

unique(gapminder$continent)
## [1] Asia     Europe   Africa   Americas Oceania 
## Levels: Africa Americas Asia Europe Oceania

La función unique() nos regresa los nombre únicos que aparecen en la variable continent del conjunto de datos. Cuando la variable es tipo factor, como es el caso, también podemos usar la función levels() para obtener las categorías.

levels(gapminder$continent)
## [1] "Africa"   "Americas" "Asia"     "Europe"   "Oceania"

Incluso, podemos usar esta misma para cambiar el nombre de algunas categorías o “niveles” (de aquí el nombre de la función). Cambiemos la categoría “Americas” por “America”.

levels(gapminder$continent)[2] = "America"
levels(gapminder$continent)
## [1] "Africa"  "America" "Asia"    "Europe"  "Oceania"

Así está mejor.

Ahora veamos las categorías de country

levels(gapminder$country)
##   [1] "Afghanistan"              "Albania"                 
##   [3] "Algeria"                  "Angola"                  
##   [5] "Argentina"                "Australia"               
##   [7] "Austria"                  "Bahrain"                 
##   [9] "Bangladesh"               "Belgium"                 
##  [11] "Benin"                    "Bolivia"                 
##  [13] "Bosnia and Herzegovina"   "Botswana"                
##  [15] "Brazil"                   "Bulgaria"                
##  [17] "Burkina Faso"             "Burundi"                 
##  [19] "Cambodia"                 "Cameroon"                
##  [21] "Canada"                   "Central African Republic"
##  [23] "Chad"                     "Chile"                   
##  [25] "China"                    "Colombia"                
##  [27] "Comoros"                  "Congo, Dem. Rep."        
##  [29] "Congo, Rep."              "Costa Rica"              
##  [31] "Cote d'Ivoire"            "Croatia"                 
##  [33] "Cuba"                     "Czech Republic"          
##  [35] "Denmark"                  "Djibouti"                
##  [37] "Dominican Republic"       "Ecuador"                 
##  [39] "Egypt"                    "El Salvador"             
##  [41] "Equatorial Guinea"        "Eritrea"                 
##  [43] "Ethiopia"                 "Finland"                 
##  [45] "France"                   "Gabon"                   
##  [47] "Gambia"                   "Germany"                 
##  [49] "Ghana"                    "Greece"                  
##  [51] "Guatemala"                "Guinea"                  
##  [53] "Guinea-Bissau"            "Haiti"                   
##  [55] "Honduras"                 "Hong Kong, China"        
##  [57] "Hungary"                  "Iceland"                 
##  [59] "India"                    "Indonesia"               
##  [61] "Iran"                     "Iraq"                    
##  [63] "Ireland"                  "Israel"                  
##  [65] "Italy"                    "Jamaica"                 
##  [67] "Japan"                    "Jordan"                  
##  [69] "Kenya"                    "Korea, Dem. Rep."        
##  [71] "Korea, Rep."              "Kuwait"                  
##  [73] "Lebanon"                  "Lesotho"                 
##  [75] "Liberia"                  "Libya"                   
##  [77] "Madagascar"               "Malawi"                  
##  [79] "Malaysia"                 "Mali"                    
##  [81] "Mauritania"               "Mauritius"               
##  [83] "Mexico"                   "Mongolia"                
##  [85] "Montenegro"               "Morocco"                 
##  [87] "Mozambique"               "Myanmar"                 
##  [89] "Namibia"                  "Nepal"                   
##  [91] "Netherlands"              "New Zealand"             
##  [93] "Nicaragua"                "Niger"                   
##  [95] "Nigeria"                  "Norway"                  
##  [97] "Oman"                     "Pakistan"                
##  [99] "Panama"                   "Paraguay"                
## [101] "Peru"                     "Philippines"             
## [103] "Poland"                   "Portugal"                
## [105] "Puerto Rico"              "Reunion"                 
## [107] "Romania"                  "Rwanda"                  
## [109] "Sao Tome and Principe"    "Saudi Arabia"            
## [111] "Senegal"                  "Serbia"                  
## [113] "Sierra Leone"             "Singapore"               
## [115] "Slovak Republic"          "Slovenia"                
## [117] "Somalia"                  "South Africa"            
## [119] "Spain"                    "Sri Lanka"               
## [121] "Sudan"                    "Swaziland"               
## [123] "Sweden"                   "Switzerland"             
## [125] "Syria"                    "Taiwan"                  
## [127] "Tanzania"                 "Thailand"                
## [129] "Togo"                     "Trinidad and Tobago"     
## [131] "Tunisia"                  "Turkey"                  
## [133] "Uganda"                   "United Kingdom"          
## [135] "United States"            "Uruguay"                 
## [137] "Venezuela"                "Vietnam"                 
## [139] "West Bank and Gaza"       "Yemen, Rep."             
## [141] "Zambia"                   "Zimbabwe"

Esas son muchas, enfoquemonos en solo una de ellas.

levels(gapminder$country)[c(28,29,56,70,71,140)]
## [1] "Congo, Dem. Rep." "Congo, Rep."      "Hong Kong, China" "Korea, Dem. Rep."
## [5] "Korea, Rep."      "Yemen, Rep."

Tal vez te pregustes porque esas en específico. Bueno, la única razón es porque no me gustan esas comas que aparecen allí, así que vamos a cambiarlas.

levels(gapminder$country)[c(28,29,56,70,71,140)] = 
  c("Congo-Kinshasa","Congo-Brazzaville","Hong Kong", 
    "North Korea", "South Korea", "Yemen")
levels(gapminder$country)[c(28,29,56,70,71,140)]
## [1] "Congo-Kinshasa"    "Congo-Brazzaville" "Hong Kong"        
## [4] "North Korea"       "South Korea"       "Yemen"

Aquí sobre la elección de los nombres para “Congo, Dem. Rep.” y “Congo, Rep.” y acá para los nombres de “Korea, Dem. Rep.” y “Korea, Rep.”.

Guardado el conjunto de datos

Ya que nuestro conjunto está “limpio”, quiza querramos guardarlo para la próxima vez que lo usemos. Lo podemos guardar como un archivo .csv con la funcion write.csv().

La función write.csv()

Esta función toma muchos argumentos, pero dos son necesarios:

x: el nombre del objeto que queremos guardar

file: el nombre del archivo en el que lo queremos guardar con extensión incluida

write.csv(gapminder, "gapminder.csv")

Hay algunos argumentos que tal vez quieras usar dentro de la función write.csv() como row.names y col.names. Busca en la documentación que hacen estos argumentos.

Otros recursos

Puedes encontrar el archivo .Rmd en mi repositorio bajo el nombre ManipulacionGapminder.Rmd en Github.