Programación Básica en R Studio - Estructura de Datos

Creación de datos ordenados

  • La ordenación de datos es un proceso fundamental en el análisis de datos, y en R, podemos llevarlo a cabo de manera coherente utilizando el paquete tidyr, que forma parte del ecosistema tidyverse. Al trabajar con tidyr, podemos seguir tres reglas clave para asegurar que nuestros conjuntos de datos estén correctamente organizados.

  • En primer lugar, cada variable debe tener su propia columna. En segundo lugar, cada observación debe tener su propia fila y, por último, cada valor debe tener su propia celda. Esto se ilustrado por el diagrama siguiente.

  • Segundo, una estructura de datos consistente es muy importante. Los paquetes que forman parte de tidyverse incluyendo dplyr y ggplot2 están diseñados para trabajar con datos ordenados, así que asegurar que que tus datos sean uniformes facilita el procesamiento eficiente de tus datos. Además, colocar las variables en columnas permite facilitar la vectorización en R.

  • Frecuentemente, al trabajar con conjuntos de datos, nos encontraremos con que estos no están organizados según los principios de los datos ordenados. Esta falta de orden puede deberse a diversas razones, y una de las más comunes es la falta de familiaridad de quienes crearon el conjunto de datos con los principios de organización de datos.

  • Las razones detrás de la desorganización de los datos pueden ser variadas. En muchos casos, las personas que recopilan o generan los datos pueden no estar al tanto de la importancia de organizarlos de manera adecuada. Pueden haber centrado su atención en la recolección de datos sin considerar la estructura final que estos deberían tener para su análisis posterior.

  • Además, la complejidad de algunos conjuntos de datos puede dificultar su organización. Al trabajar con grandes volúmenes de datos o datos provenientes de múltiples fuentes, puede resultar desafiante mantener una estructura ordenada y coherente. Esto puede llevar a conjuntos de datos desordenados que requieren trabajo adicional para su limpieza y organización.

  • El primer paso es averiguar cuáles son las variables y observaciones del conjunto de datos. Esto le facilitará la comprensión de lo que deben ser las columnas y las. Además, también tendrá que resolver uno o dos problemas comunes. Tendrá que averiguar si una variable está repartida en varias columnas, y si una observación está dispersa en varias filas. Estos conceptos se conocen como reunión y dispersión. Examinaremos examinaremos más a fondo estos conceptos en los ejercicios de este capítulo

En este capítulo trataremos los siguientes temas:

  • Recopilación
  • Distribución
  • Separación
  • Unión

Recopilación

Un problema común en muchos conjuntos de datos es que los nombres de las columnas no son variables sino valores de una variable. En la figura siguiente, las columnas 1999 y 2000 son en realidad valores de la variable YEAR. Cada fila de la tabla existente representa en realidad dos observaciones. El paquete tidyr puede utilizarse para reunir estas columnas existentes en una nueva variable. En este caso, tenemos que crear una nueva columna columna llamada YEAR y luego reunir en esta los valores existentes en las columnas 1999 y 2000.

La función gather() del paquete tidyr es la idonea para la reestrucutración del df por ejemplo

gather("1999", "2000", key = "year", value = "cases")

Hay tres parámetros de la función gather(). 1) El conjunto de columnas que representan lo que deberían ser valores y no variables. Estas serían las columnas 1999 y 2000. 2) Nombrar la variable de la nueva columna. Esto también se llama la clave key, y en este caso será la variable del año. 3) Por último, tendrás que proporcionar el valor value, que es el nombre de la variable cuyos valores se reparten por las celdas.

Practiquemos lo anterior con el siguiente ejercicio. como primera media descargue el archivo CountryPopulation.csv localizado en Bases-de-datos. abra el archivo en una hoja de excel solo para visualizarlo, si realiza alguna modificación procure no guardarla.

Las columnas de cada año representan valores, no variables. Estas columnas deben reunirse en un nuevo par de variables que representen el año y la población. En este ejercicio utilizarás la función gather() para realizar esta tarea de ordenación de datos.

Carguemos el df en nuestro entorno

dfPop = read_csv("CountryPopulation.csv", col_names = TRUE)
## Rows: 264 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Country Name, Country Code
## dbl (8): 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
knitr::kable(head(dfPop, 15))
Country Name Country Code 2010 2011 2012 2013 2014 2015 2016 2017
Aruba ABW 101669 102053 102577 103187 103795 104341 104822 105264
Afghanistan AFG 28803167 29708599 30696958 31731688 32758020 33736494 34656032 35530081
Angola AGO 23369131 24218565 25096150 25998340 26920466 27859305 28813463 29784193
Albania ALB 2913021 2905195 2900401 2895092 2889104 2880703 2876101 2873457
Andorra AND 84449 83751 82431 80788 79223 78014 77281 76965
Arab World ARB 356508908 364895878 373306993 381702086 390043028 398304960 406452690 414491886
United Arab Emirates ARE 8270684 8672475 8900453 9006263 9070867 9154302 9269612 9400145
Argentina ARG 41223889 41656879 42096739 42539925 42981515 43417765 43847430 44271041
Armenia ARM 2877311 2875581 2881922 2893509 2906220 2916950 2924816 2930450
American Samoa ASM 55637 55320 55230 55307 55437 55537 55599 55641
Antigua and Barbuda ATG 94661 95719 96777 97824 98875 99923 100963 102012
Australia AUS 22031750 22340024 22742475 23145901 23504138 23850784 24210809 24598933
Austria AUT 8363404 8391643 8429991 8479823 8546356 8642699 8736668 8809212
Azerbaijan AZE 9054332 9173082 9295784 9416801 9535079 9649341 9757812 9862429
Burundi BDI 8766930 9043508 9319710 9600186 9891790 10199270 10524117 10864245

Ahora utilice la función gather() para reestructurar el df de la siguiente forma

dfPop2 = gather(dfPop, 
                "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", 
                key = "YEAR", 
                value = "POPULATION")
knitr::kable(head(dfPop2, 10))
Country Name Country Code YEAR POPULATION
Aruba ABW 2010 101669
Afghanistan AFG 2010 28803167
Angola AGO 2010 23369131
Albania ALB 2010 2913021
Andorra AND 2010 84449
Arab World ARB 2010 356508908
United Arab Emirates ARE 2010 8270684
Argentina ARG 2010 41223889
Armenia ARM 2010 2877311
American Samoa ASM 2010 55637

¿que sucedería, si en un caso hipotético nos encontramos con un gran número de columna de este tipo? Para ello, la opción mas eficiente sería

years <- colnames(dfPop)[grep("^\\d{4}$", colnames(dfPop))]

dfPop3 <- dfPop %>%
  gather(key = "YEAR", value = "POPULATION", all_of(years))

knitr::kable(head(dfPop3, 10))
Country Name Country Code YEAR POPULATION
Aruba ABW 2010 101669
Afghanistan AFG 2010 28803167
Angola AGO 2010 23369131
Albania ALB 2010 2913021
Andorra AND 2010 84449
Arab World ARB 2010 356508908
United Arab Emirates ARE 2010 8270684
Argentina ARG 2010 41223889
Armenia ARM 2010 2877311
American Samoa ASM 2010 55637

Donde, en expresiones regulares, "^\\d{4}$" tiene el siguiente significado:

  • ^: Representa el inicio de una cadena.
  • \\d: Representa un dígito.
  • {4}: Indica que el elemento anterior (\\d, en este caso) debe aparecer exactamente 4 veces.
  • $: Representa el final de una cadena.

En resumen, "^\\d{4}$" coincide con cualquier cadena que contenga exactamente 4 dígitos y no contenga ningún otro carácter adicional antes o después de los dígitos.

Distribución

La distribución es lo contrario de la recopilación y se utiliza cuando una observación se distribuye en varias filas. En el diagrama siguiente, la tabla debe definir una observación de un país por año. Sin embargo, observará que está repartida en dos filas. Una fila para cases y otra para population.

Para ello, la función spread() soluciona este problema. La función spread() toma dos parámetros: la columna que contiene los nombres de las variables repetidas, conocida como key y una columna que contiene valores de múltiples variables, que llamamos value

Cargue el conjunto de datos DSR Ubicado aquí llamadado table2 con extensión .rdata utilizando el código que ve a continuación escribiendo en el panel de la consola.

load("table2.rdata")
knitr::kable(head(table2, 5))
country year key value
Afghanistan 1999 cases 745
Afghanistan 1999 population 19987071
Afghanistan 2000 cases 2666
Afghanistan 2000 population 20595360
Brazil 1999 cases 37737

Utilice la función spread() para corregir este problema. Recuerde instalar el paquete

table2b <- spread(table2, key = key, value = value)
knitr::kable(head(table2b))
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

Separación

Otro caso común es el de dos variables que se colocan en la misma columna. Por ejemplo, la hoja de cálculo siguiente tiene una columna State-County Name que en realidad contiene dos variables separadas por una barra.

La función separate() puede utilizarse para dividir una columna en varias columnas dividiendo por un separador. Por defecto, la función separate() buscará automáticamente cualquier carácter no alfanumérico o se puede definir un carácter específico

En la carpeta de base-de-datos hay un archivo llamado usco2005.csv. Descargue y abra este archivo, por ejemplo con Microsoft Excel, o algún otro tipo de software de hoja de cálculo, posterior a ello carguela en el entorno de esta forma

df = read_csv("usco2005.csv", col_names = TRUE)
## Rows: 3222 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): STATE, State-County Name
## dbl (4): STATEFIPS, COUNTYFIPS, FIPS, TP-TotPop
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
knitr::kable(head(df, 10))
STATE STATEFIPS COUNTYFIPS FIPS State-County Name TP-TotPop
AL 1 1 1001 Alabama-Autauga County 48.612
AL 1 3 1003 Alabama-Baldwin County 162.586
AL 1 5 1005 Alabama-Barbour County 28.414
AL 1 7 1007 Alabama-Bibb County 21.516
AL 1 9 1009 Alabama-Blount County 55.725
AL 1 11 1011 Alabama-Bullock County 11.055
AL 1 13 1013 Alabama-Butler County 20.766
AL 1 15 1015 Alabama-Calhoun County 112.141
AL 1 17 1017 Alabama-Chambers County 35.460
AL 1 19 1019 Alabama-Cherokee County 24.522

Utilice la función separate() para separar el contenido de la columna State-County Name en las columnas StateAbbrev y CountyName

df2 = separate(df, "State-County Name",into = c("StateAbbrev", "CountyName"))
## Warning: Expected 2 pieces. Additional pieces discarded in 3222 rows [1, 2, 3, 4, 5, 6,
## 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...].
knitr::kable(head(df2, 10))
STATE STATEFIPS COUNTYFIPS FIPS StateAbbrev CountyName TP-TotPop
AL 1 1 1001 Alabama Autauga 48.612
AL 1 3 1003 Alabama Baldwin 162.586
AL 1 5 1005 Alabama Barbour 28.414
AL 1 7 1007 Alabama Bibb 21.516
AL 1 9 1009 Alabama Blount 55.725
AL 1 11 1011 Alabama Bullock 11.055
AL 1 13 1013 Alabama Butler 20.766
AL 1 15 1015 Alabama Calhoun 112.141
AL 1 17 1017 Alabama Chambers 35.460
AL 1 19 1019 Alabama Cherokee 24.522

Unión

La función unite() es exactamente lo contrario de separate(), ya que combina varias columnas en una sola. Aunque no se utiliza tan a menudo como separate(), puede haber ocasiones en las que necesite la funcionalidad proporcionada por unite(). La idea de este ejercicio es que se una el df separado anteriormente

En el panel de la consola, añada el código que ve a continuación para unir las columnas StateAbbrev y CountyName en una sola columna. Por defecto unite() realiza unión con base en la expresión regular "_", "unite(data, col, ..., sep = "_", remove = TRUE)"

df3 = unite(df2, State_County_Name, StateAbbrev, CountyName)
knitr::kable(head(df3, 10))
STATE STATEFIPS COUNTYFIPS FIPS State_County_Name TP-TotPop
AL 1 1 1001 Alabama_Autauga 48.612
AL 1 3 1003 Alabama_Baldwin 162.586
AL 1 5 1005 Alabama_Barbour 28.414
AL 1 7 1007 Alabama_Bibb 21.516
AL 1 9 1009 Alabama_Blount 55.725
AL 1 11 1011 Alabama_Bullock 11.055
AL 1 13 1013 Alabama_Butler 20.766
AL 1 15 1015 Alabama_Calhoun 112.141
AL 1 17 1017 Alabama_Chambers 35.460
AL 1 19 1019 Alabama_Cherokee 24.522