El objetivo de este markdown es plasmar las pautas principales para tener nuestros datos correctamente planteados y organizados.
library(tidyverse)
Todos los datos con los que vayamos a trabajar siempre se van a poder representar de multiples formas. Este ejemplo muestra la misma informacion organizada de diferentes maneras.
table1
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
table2
## # A tibble: 12 x 4
## country year type count
## <chr> <int> <chr> <int>
## 1 Afghanistan 1999 cases 745
## 2 Afghanistan 1999 population 19987071
## 3 Afghanistan 2000 cases 2666
## 4 Afghanistan 2000 population 20595360
## 5 Brazil 1999 cases 37737
## 6 Brazil 1999 population 172006362
## 7 Brazil 2000 cases 80488
## 8 Brazil 2000 population 174504898
## 9 China 1999 cases 212258
## 10 China 1999 population 1272915272
## 11 China 2000 cases 213766
## 12 China 2000 population 1280428583
table3
## # A tibble: 6 x 3
## country year rate
## * <chr> <int> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
table4a
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 745 2666
## 2 Brazil 37737 80488
## 3 China 212258 213766
table4b
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 19987071 20595360
## 2 Brazil 172006362 174504898
## 3 China 1272915272 1280428583
Todos son representaciones de los mismos datos pero no pueden ser usados de la misma manera.
Hay tres reglas principales que definen nuestro dataset como organizado o “tidy”.
knitr::include_graphics("Tidy data.png")
A caption
Aunque creamos que no, la mayoria de la informacion que nos encontremos estara desorganizada y no adaptada a los estandares que hemos comentado anteriormente.
Por ello, el primer paso es siempre descubrir cuales son las variables y observaciones
El segundo paso, es resolver uno de estos dos problemas que son bastante comunes. Una variable que aparezca entre multiples columnas o una observacion que se disperse a través de multiples filas.
Para solucionar todos estos aspectos utilizaremos las funciones de gather() y spread().
Gathering
Un problema comun de los dataset es cuando algunos de los nombres de las columnas no son nombres de variables, si no valores de las variables.
table4a
## # A tibble: 3 x 3
## country `1999` `2000`
## * <chr> <int> <int>
## 1 Afghanistan 745 2666
## 2 Brazil 37737 80488
## 3 China 212258 213766
Necesitamos que esas columnas se junten en un nuevo par de variables. Para ello, definiremos 3 parametros.
table4a %>%
gather("1999","2000", key = "year", value = "cases")
## # A tibble: 6 x 3
## country year cases
## <chr> <chr> <int>
## 1 Afghanistan 1999 745
## 2 Brazil 1999 37737
## 3 China 1999 212258
## 4 Afghanistan 2000 2666
## 5 Brazil 2000 80488
## 6 China 2000 213766
knitr::include_graphics("Gathering table.png")
A caption
Para combinar diferentes tablas podemos utilizar la funcion de dplyr left_join().
Spreading
Spreading es lo contrario a gathering. Cuando una observacion se encuentra dispersa entre multiples filas.
En este caso solo necesitamos definir dos parametros:
spread(table2, key = type, value = count)
## # A tibble: 6 x 4
## country year cases population
## <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
knitr::include_graphics("Spreading table.png")
A caption
Separating
Separate() separa una columna en multiples repartiendolas donde aparezca un separador de caracter.
table3
## # A tibble: 6 x 3
## country year rate
## * <chr> <int> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
table3 %>%
separate(rate, into = c("cases", "population"), sep = "/", convert = TRUE)
## # A tibble: 6 x 4
## country year cases population
## * <chr> <int> <int> <int>
## 1 Afghanistan 1999 745 19987071
## 2 Afghanistan 2000 2666 20595360
## 3 Brazil 1999 37737 172006362
## 4 Brazil 2000 80488 174504898
## 5 China 1999 212258 1272915272
## 6 China 2000 213766 1280428583
Por defecto separate() dividira los valores donde vea un caracter no alfanumerico, pero podemos marcar la separacion que quereamos con sep=.
Por otro lado, los tipos de columnas de case y population son caracteres porque la transformacion se realiza asi por defecto. Pero no es util ya que son numeros, con la funcion convert solucionamos ese problema.
knitr::include_graphics("Separating table.png")
A caption
Unite
Unite() es lo contrario a separate. Combinas multiples columnas en una unica columna.
table5
## # A tibble: 6 x 4
## country century year rate
## * <chr> <chr> <chr> <chr>
## 1 Afghanistan 19 99 745/19987071
## 2 Afghanistan 20 00 2666/20595360
## 3 Brazil 19 99 37737/172006362
## 4 Brazil 20 00 80488/174504898
## 5 China 19 99 212258/1272915272
## 6 China 20 00 213766/1280428583
table5 %>%
unite(new, century, year, sep = "")
## # A tibble: 6 x 3
## country new rate
## <chr> <chr> <chr>
## 1 Afghanistan 1999 745/19987071
## 2 Afghanistan 2000 2666/20595360
## 3 Brazil 1999 37737/172006362
## 4 Brazil 2000 80488/174504898
## 5 China 1999 212258/1272915272
## 6 China 2000 213766/1280428583
A la hora de trabajar con diferentes dataset siempre apareceran problemas o diferentes formar de trabajar con los missing values.
Un Missing value nos puede aparecer de dos diferentes manera:
Por ejemplo,
stocks <- tibble(
year = c(2015, 2015, 2015, 2015, 2016, 2016, 2016),
qtr = c( 1, 2, 3, 4, 2, 3, 4),
return = c(1.88, 0.59, 0.35, NA, 0.92, 0.17, 2.66)
)
En este caso, tenemos como missing values, un valor faltante en el Q4 de 2015 y en el Q1 de 2016 ni si quiera tenemos los datos.
Lo podriamos ver de esta manera:
Un valor faltante explícito es la presencia de una ausencia; Un valor implícito que falta es la ausencia de una presencia
Por ejemplo, podemos hacer que los missing values implicitos sean explicitos poniendo los años en las columnas.
stocks %>%
spread(year, return)
## # A tibble: 4 x 3
## qtr `2015` `2016`
## <dbl> <dbl> <dbl>
## 1 1 1.88 NA
## 2 2 0.59 0.92
## 3 3 0.35 0.17
## 4 4 NA 2.66
Por otro lado, utilizando na.rm = TRUE podemos transformar los missing values explicitos en implicitos.
stocks %>%
spread(year, return) %>%
gather(year, return, "2015", "2016", na.rm = TRUE)
## # A tibble: 6 x 3
## qtr year return
## * <dbl> <chr> <dbl>
## 1 1 2015 1.88
## 2 2 2015 0.59
## 3 3 2015 0.35
## 4 2 2016 0.92
## 5 3 2016 0.17
## 6 4 2016 2.66
Otra herramienta es la funcion complete() para hacer los missing values explicitos.
En este caso, complete toma un conjunto de columnas y encuentra todas las combinaciones únicas. Luego se asegura de que el conjunto de datos original contenga todos esos valores, completando las NA explícitas cuando sea necesario.
stocks %>%
complete(year, qtr)
## # A tibble: 8 x 3
## year qtr return
## <dbl> <dbl> <dbl>
## 1 2015 1 1.88
## 2 2015 2 0.59
## 3 2015 3 0.35
## 4 2015 4 NA
## 5 2016 1 NA
## 6 2016 2 0.92
## 7 2016 3 0.17
## 8 2016 4 2.66
Por ultimo, otra herramienta es la funcion fill().
Cuando una fuente de datos se ha utilizado principalmente para la entrada de datos, los valores faltantes indican que el valor anterior debe mantenerse
treatment <- tribble(
~person, ~treatment, ~responde,
"Derrick Whitmore", 1, 7,
NA, 2, 10,
NA, 3, 9,
"Katherine Burke", 1, 4)
treatment %>%
fill(person)
## # A tibble: 4 x 3
## person treatment responde
## <chr> <dbl> <dbl>
## 1 Derrick Whitmore 1 7
## 2 Derrick Whitmore 2 10
## 3 Derrick Whitmore 3 9
## 4 Katherine Burke 1 4
Aplicaremos todo lo que hemos tratado anteriormente en este dataset que recoge los casos de tuberculosis anuales por año, pais, edad, genero y metodo de diagnostico.
Asi se nos muestra la tabla inicial:
who
## # A tibble: 7,240 x 60
## country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534
## <chr> <chr> <chr> <int> <int> <int> <int>
## 1 Afghan~ AF AFG 1980 NA NA NA
## 2 Afghan~ AF AFG 1981 NA NA NA
## 3 Afghan~ AF AFG 1982 NA NA NA
## 4 Afghan~ AF AFG 1983 NA NA NA
## 5 Afghan~ AF AFG 1984 NA NA NA
## 6 Afghan~ AF AFG 1985 NA NA NA
## 7 Afghan~ AF AFG 1986 NA NA NA
## 8 Afghan~ AF AFG 1987 NA NA NA
## 9 Afghan~ AF AFG 1988 NA NA NA
## 10 Afghan~ AF AFG 1989 NA NA NA
## # ... with 7,230 more rows, and 53 more variables: new_sp_m3544 <int>,
## # new_sp_m4554 <int>, new_sp_m5564 <int>, new_sp_m65 <int>,
## # new_sp_f014 <int>, new_sp_f1524 <int>, new_sp_f2534 <int>,
## # new_sp_f3544 <int>, new_sp_f4554 <int>, new_sp_f5564 <int>,
## # new_sp_f65 <int>, new_sn_m014 <int>, new_sn_m1524 <int>,
## # new_sn_m2534 <int>, new_sn_m3544 <int>, new_sn_m4554 <int>,
## # new_sn_m5564 <int>, new_sn_m65 <int>, new_sn_f014 <int>,
## # new_sn_f1524 <int>, new_sn_f2534 <int>, new_sn_f3544 <int>,
## # new_sn_f4554 <int>, new_sn_f5564 <int>, new_sn_f65 <int>,
## # new_ep_m014 <int>, new_ep_m1524 <int>, new_ep_m2534 <int>,
## # new_ep_m3544 <int>, new_ep_m4554 <int>, new_ep_m5564 <int>,
## # new_ep_m65 <int>, new_ep_f014 <int>, new_ep_f1524 <int>,
## # new_ep_f2534 <int>, new_ep_f3544 <int>, new_ep_f4554 <int>,
## # new_ep_f5564 <int>, new_ep_f65 <int>, newrel_m014 <int>,
## # newrel_m1524 <int>, newrel_m2534 <int>, newrel_m3544 <int>,
## # newrel_m4554 <int>, newrel_m5564 <int>, newrel_m65 <int>,
## # newrel_f014 <int>, newrel_f1524 <int>, newrel_f2534 <int>,
## # newrel_f3544 <int>, newrel_f4554 <int>, newrel_f5564 <int>,
## # newrel_f65 <int>
Y esta es la tabla final con todo lo aplicado.
who %>%
gather(code, value, new_sp_m014:newrel_f65, na.rm = TRUE) %>%
mutate(code = stringr::str_replace(code,"newrel","new_rel")) %>%
separate(code, c("new", "var", "sexage")) %>%
select(-new, -iso2, -iso3) %>%
separate(sexage, c("sex", "age", sep = 1))
## # A tibble: 76,046 x 7
## country year var sex age `1` value
## <chr> <int> <chr> <chr> <chr> <chr> <int>
## 1 Afghanistan 1997 sp m014 <NA> <NA> 0
## 2 Afghanistan 1998 sp m014 <NA> <NA> 30
## 3 Afghanistan 1999 sp m014 <NA> <NA> 8
## 4 Afghanistan 2000 sp m014 <NA> <NA> 52
## 5 Afghanistan 2001 sp m014 <NA> <NA> 129
## 6 Afghanistan 2002 sp m014 <NA> <NA> 90
## 7 Afghanistan 2003 sp m014 <NA> <NA> 127
## 8 Afghanistan 2004 sp m014 <NA> <NA> 139
## 9 Afghanistan 2005 sp m014 <NA> <NA> 151
## 10 Afghanistan 2006 sp m014 <NA> <NA> 193
## # ... with 76,036 more rows