RStudio provee una gran diversidad de recursos para el manejo y transformación de los datos
Los archivos que obtenemos de una base de datos o que generamos en nuestras investigaciones, usualmente contienen más datos de los que necesitamos para una exploración, visualización o análisis estadístico; en estos casos podemos seleccionar aquellos casos y/o variables que deseamos usando procedimientos de RStudio. En muchos casos, los datos requieren transformaciones, para cambiar unidades o escala. Otras manipulaciones que muchas veces queremos realizar, incluyen: eliminación de valores incorrectos, cambio de formato o estructura de los datos.
Al finalizar esta sección podrás realizar diversas manipulaciones de los datos usando los paquetes dplyr y tidyr
Usaremos el archivo de datos de muertes asociadas a COVID-19 en los Estados Unidos, obtenido del CDC (ver módulo anterior, tema 1.8.6), coviddata.csv. Vamos a eliminar columnas que no nos interesan: Data as of, Start Date y Footnote. Usaremos las funciones select y filter.
## activar paquetes a usar
library(readr)
library(dplyr)
## importar los datos a una variable
# usaremos un lector de datos .csv diferente, en readr
# crea un tibble, forma especial de data.frame
# produce una lista de las columnas y su tipo de dato
covid_19 <- read_csv("data/coviddata.csv")
str(covid_19)
## spec_tbl_df [57,834 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ Data As Of : chr [1:57834] "06/16/2021" "06/16/2021" "06/16/2021" "06/16/2021" ...
## $ Start Date : chr [1:57834] "01/01/2020" "01/01/2020" "01/01/2020" "01/01/2020" ...
## $ End Date : chr [1:57834] "06/12/2021" "06/12/2021" "06/12/2021" "06/12/2021" ...
## $ Group : chr [1:57834] "By Total" "By Total" "By Total" "By Total" ...
## $ Year : logi [1:57834] NA NA NA NA NA NA ...
## $ Month : logi [1:57834] NA NA NA NA NA NA ...
## $ State : chr [1:57834] "United States" "United States" "United States" "United States" ...
## $ Sex : chr [1:57834] "All Sexes" "All Sexes" "All Sexes" "All Sexes" ...
## $ Age Group : chr [1:57834] "All Ages" "Under 1 year" "0-17 years" "1-4 years" ...
## $ COVID-19 Deaths : num [1:57834] 590091 81 322 37 112 ...
## $ Total Deaths : num [1:57834] 4791858 26746 46977 4859 7811 ...
## $ Pneumonia Deaths : num [1:57834] 520776 288 773 156 222 ...
## $ Pneumonia and COVID-19 Deaths : num [1:57834] 289584 12 61 6 24 ...
## $ Influenza Deaths : num [1:57834] 9161 21 183 64 77 ...
## $ Pneumonia, Influenza, or COVID-19 Deaths: num [1:57834] 829164 378 1217 251 387 ...
## $ Footnote : chr [1:57834] NA NA NA NA ...
## - attr(*, "problems")= tibble [99,144 × 5] (S3: tbl_df/tbl/data.frame)
## ..$ row : int [1:99144] 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 ...
## ..$ col : chr [1:99144] "Year" "Year" "Year" "Year" ...
## ..$ expected: chr [1:99144] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
## ..$ actual : chr [1:99144] "2020" "2020" "2020" "2020" ...
## ..$ file : chr [1:99144] "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" ...
## - attr(*, "spec")=
## .. cols(
## .. `Data As Of` = col_character(),
## .. `Start Date` = col_character(),
## .. `End Date` = col_character(),
## .. Group = col_character(),
## .. Year = col_logical(),
## .. Month = col_logical(),
## .. State = col_character(),
## .. Sex = col_character(),
## .. `Age Group` = col_character(),
## .. `COVID-19 Deaths` = col_double(),
## .. `Total Deaths` = col_double(),
## .. `Pneumonia Deaths` = col_double(),
## .. `Pneumonia and COVID-19 Deaths` = col_double(),
## .. `Influenza Deaths` = col_double(),
## .. `Pneumonia, Influenza, or COVID-19 Deaths` = col_double(),
## .. Footnote = col_character()
## .. )
# usaremos select para seleccionar las columnas que queremos
# son más las que queremos: - para eliminar las que no queremos
covid_select <- select(covid_19, -"Data As Of", -"Start Date", -Footnote)
str(covid_select)
## tibble [57,834 × 13] (S3: tbl_df/tbl/data.frame)
## $ End Date : chr [1:57834] "06/12/2021" "06/12/2021" "06/12/2021" "06/12/2021" ...
## $ Group : chr [1:57834] "By Total" "By Total" "By Total" "By Total" ...
## $ Year : logi [1:57834] NA NA NA NA NA NA ...
## $ Month : logi [1:57834] NA NA NA NA NA NA ...
## $ State : chr [1:57834] "United States" "United States" "United States" "United States" ...
## $ Sex : chr [1:57834] "All Sexes" "All Sexes" "All Sexes" "All Sexes" ...
## $ Age Group : chr [1:57834] "All Ages" "Under 1 year" "0-17 years" "1-4 years" ...
## $ COVID-19 Deaths : num [1:57834] 590091 81 322 37 112 ...
## $ Total Deaths : num [1:57834] 4791858 26746 46977 4859 7811 ...
## $ Pneumonia Deaths : num [1:57834] 520776 288 773 156 222 ...
## $ Pneumonia and COVID-19 Deaths : num [1:57834] 289584 12 61 6 24 ...
## $ Influenza Deaths : num [1:57834] 9161 21 183 64 77 ...
## $ Pneumonia, Influenza, or COVID-19 Deaths: num [1:57834] 829164 378 1217 251 387 ...
## - attr(*, "problems")= tibble [99,144 × 5] (S3: tbl_df/tbl/data.frame)
## ..$ row : int [1:99144] 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 ...
## ..$ col : chr [1:99144] "Year" "Year" "Year" "Year" ...
## ..$ expected: chr [1:99144] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
## ..$ actual : chr [1:99144] "2020" "2020" "2020" "2020" ...
## ..$ file : chr [1:99144] "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" ...
# usaremos filter para quedarnos con los datos de Puerto Rico
covid_filter <- filter(covid_select, State == "Puerto Rico")
str(covid_filter)
## tibble [1,071 × 13] (S3: tbl_df/tbl/data.frame)
## $ End Date : chr [1:1071] "06/12/2021" "06/12/2021" "06/12/2021" "06/12/2021" ...
## $ Group : chr [1:1071] "By Total" "By Total" "By Total" "By Total" ...
## $ Year : logi [1:1071] NA NA NA NA NA NA ...
## $ Month : logi [1:1071] NA NA NA NA NA NA ...
## $ State : chr [1:1071] "Puerto Rico" "Puerto Rico" "Puerto Rico" "Puerto Rico" ...
## $ Sex : chr [1:1071] "All Sexes" "All Sexes" "All Sexes" "All Sexes" ...
## $ Age Group : chr [1:1071] "All Ages" "Under 1 year" "0-17 years" "1-4 years" ...
## $ COVID-19 Deaths : num [1:1071] 2433 0 NA 0 NA ...
## $ Total Deaths : num [1:1071] 42308 184 282 29 29 ...
## $ Pneumonia Deaths : num [1:1071] 6026 NA NA NA NA ...
## $ Pneumonia and COVID-19 Deaths : num [1:1071] 1719 0 NA 0 0 ...
## $ Influenza Deaths : num [1:1071] 107 0 NA NA 0 0 NA NA NA 0 ...
## $ Pneumonia, Influenza, or COVID-19 Deaths: num [1:1071] 6839 NA NA NA NA ...
## - attr(*, "problems")= tibble [99,144 × 5] (S3: tbl_df/tbl/data.frame)
## ..$ row : int [1:99144] 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 ...
## ..$ col : chr [1:99144] "Year" "Year" "Year" "Year" ...
## ..$ expected: chr [1:99144] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
## ..$ actual : chr [1:99144] "2020" "2020" "2020" "2020" ...
## ..$ file : chr [1:99144] "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" ...
En el ejemplo anterior vemos que para llegar al objeto final, covid_filter, tuvimos que crear un paso intermedio, covid_select. En este caso no es muy importante, pero cuando se hacen múltiples manipulaciones y transformaciones, puede ser engorroso y fuente de errores. Una alternativa es usar lo que se conocen como ‘pipes’ para conectar los procedimientos y que los datos fluyan como en una tubería (pipe). El conector que se usa es: %>%; se puede generar usando: control + shift + M (en MacOS).
# creamos un nuevo objeto con los datos seleccionados y filtrados
# el archivo original covid_19 no se modifica
covid_PR <- covid_19 %>%
select(-"Data As Of", -"Start Date", -Footnote) %>%
filter(State == "Puerto Rico")
str(covid_PR)
## tibble [1,071 × 13] (S3: tbl_df/tbl/data.frame)
## $ End Date : chr [1:1071] "06/12/2021" "06/12/2021" "06/12/2021" "06/12/2021" ...
## $ Group : chr [1:1071] "By Total" "By Total" "By Total" "By Total" ...
## $ Year : logi [1:1071] NA NA NA NA NA NA ...
## $ Month : logi [1:1071] NA NA NA NA NA NA ...
## $ State : chr [1:1071] "Puerto Rico" "Puerto Rico" "Puerto Rico" "Puerto Rico" ...
## $ Sex : chr [1:1071] "All Sexes" "All Sexes" "All Sexes" "All Sexes" ...
## $ Age Group : chr [1:1071] "All Ages" "Under 1 year" "0-17 years" "1-4 years" ...
## $ COVID-19 Deaths : num [1:1071] 2433 0 NA 0 NA ...
## $ Total Deaths : num [1:1071] 42308 184 282 29 29 ...
## $ Pneumonia Deaths : num [1:1071] 6026 NA NA NA NA ...
## $ Pneumonia and COVID-19 Deaths : num [1:1071] 1719 0 NA 0 0 ...
## $ Influenza Deaths : num [1:1071] 107 0 NA NA 0 0 NA NA NA 0 ...
## $ Pneumonia, Influenza, or COVID-19 Deaths: num [1:1071] 6839 NA NA NA NA ...
## - attr(*, "problems")= tibble [99,144 × 5] (S3: tbl_df/tbl/data.frame)
## ..$ row : int [1:99144] 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 ...
## ..$ col : chr [1:99144] "Year" "Year" "Year" "Year" ...
## ..$ expected: chr [1:99144] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
## ..$ actual : chr [1:99144] "2020" "2020" "2020" "2020" ...
## ..$ file : chr [1:99144] "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" ...
Tenemos nombres de las columnas que son muy largos, y nos pueden crear errores en los análisis. Vamos a usar otra función de dplyr, llamada rename.
# producimos un nuevo tibble con los nuevos nombres
covid_PR_1 <- covid_PR %>%
rename(date = "End Date", state = State, sex = Sex, age = "Age Group", c_deaths = "COVID-19 Deaths", t_deaths = "Total Deaths", p_deaths = "Pneumonia Deaths", pc_deaths = "Pneumonia and COVID-19 Deaths", i_deaths = "Influenza Deaths", pic_deaths = "Pneumonia, Influenza, or COVID-19 Deaths")
str(covid_PR_1)
## tibble [1,071 × 13] (S3: tbl_df/tbl/data.frame)
## $ date : chr [1:1071] "06/12/2021" "06/12/2021" "06/12/2021" "06/12/2021" ...
## $ Group : chr [1:1071] "By Total" "By Total" "By Total" "By Total" ...
## $ Year : logi [1:1071] NA NA NA NA NA NA ...
## $ Month : logi [1:1071] NA NA NA NA NA NA ...
## $ state : chr [1:1071] "Puerto Rico" "Puerto Rico" "Puerto Rico" "Puerto Rico" ...
## $ sex : chr [1:1071] "All Sexes" "All Sexes" "All Sexes" "All Sexes" ...
## $ age : chr [1:1071] "All Ages" "Under 1 year" "0-17 years" "1-4 years" ...
## $ c_deaths : num [1:1071] 2433 0 NA 0 NA ...
## $ t_deaths : num [1:1071] 42308 184 282 29 29 ...
## $ p_deaths : num [1:1071] 6026 NA NA NA NA ...
## $ pc_deaths : num [1:1071] 1719 0 NA 0 0 ...
## $ i_deaths : num [1:1071] 107 0 NA NA 0 0 NA NA NA 0 ...
## $ pic_deaths: num [1:1071] 6839 NA NA NA NA ...
## - attr(*, "problems")= tibble [99,144 × 5] (S3: tbl_df/tbl/data.frame)
## ..$ row : int [1:99144] 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 ...
## ..$ col : chr [1:99144] "Year" "Year" "Year" "Year" ...
## ..$ expected: chr [1:99144] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
## ..$ actual : chr [1:99144] "2020" "2020" "2020" "2020" ...
## ..$ file : chr [1:99144] "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" ...
Vamos ahora a crear una nueva columna con el porcentaje de muertes por CoviD-19 del total de muertes a la fecha. Usaremos la función mutate.
# realizamos los cambios sobre el mismo tibble
covid_PR_1 <- covid_PR_1 %>%
mutate(porc_ct = (c_deaths / t_deaths) * 100) %>%
mutate(date = as.Date(date, format = "%m/%d/%Y"))
str(covid_PR_1)
## tibble [1,071 × 14] (S3: tbl_df/tbl/data.frame)
## $ date : Date[1:1071], format: "2021-06-12" "2021-06-12" ...
## $ Group : chr [1:1071] "By Total" "By Total" "By Total" "By Total" ...
## $ Year : logi [1:1071] NA NA NA NA NA NA ...
## $ Month : logi [1:1071] NA NA NA NA NA NA ...
## $ state : chr [1:1071] "Puerto Rico" "Puerto Rico" "Puerto Rico" "Puerto Rico" ...
## $ sex : chr [1:1071] "All Sexes" "All Sexes" "All Sexes" "All Sexes" ...
## $ age : chr [1:1071] "All Ages" "Under 1 year" "0-17 years" "1-4 years" ...
## $ c_deaths : num [1:1071] 2433 0 NA 0 NA ...
## $ t_deaths : num [1:1071] 42308 184 282 29 29 ...
## $ p_deaths : num [1:1071] 6026 NA NA NA NA ...
## $ pc_deaths : num [1:1071] 1719 0 NA 0 0 ...
## $ i_deaths : num [1:1071] 107 0 NA NA 0 0 NA NA NA 0 ...
## $ pic_deaths: num [1:1071] 6839 NA NA NA NA ...
## $ porc_ct : num [1:1071] 5.75 0 NA 0 NA ...
## - attr(*, "problems")= tibble [99,144 × 5] (S3: tbl_df/tbl/data.frame)
## ..$ row : int [1:99144] 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 ...
## ..$ col : chr [1:99144] "Year" "Year" "Year" "Year" ...
## ..$ expected: chr [1:99144] "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" "1/0/T/F/TRUE/FALSE" ...
## ..$ actual : chr [1:99144] "2020" "2020" "2020" "2020" ...
## ..$ file : chr [1:99144] "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" "'data/coviddata.csv'" ...
De nuestro tibble podemos extraer algunos de los datos y rearreglarlos en forma de una tabla. Para esto usaremos una función del paquete tidyr: spread. Queremos extraer los datos de muertes por CoviD-19 (c_deaths) por sexo (sex) y grupo de edad (age). Antes debemos seleccionar las columnas de las cuales nos interesa obtener la información.
# activar tidyr
library(tidyr)
# uso de spread luego de select para expandir los datos por sexo
covid_sex <- covid_PR_1 %>%
filter(Group == "By Month") %>%
select(date, sex, age, c_deaths) %>%
spread(sex, c_deaths)
head(covid_sex, 20)
## # A tibble: 20 x 5
## date age `All Sexes` Female Male
## <date> <chr> <dbl> <dbl> <dbl>
## 1 2020-01-31 0-17 years 0 0 0
## 2 2020-01-31 1-4 years 0 0 0
## 3 2020-01-31 15-24 years 0 0 0
## 4 2020-01-31 18-29 years 0 0 0
## 5 2020-01-31 25-34 years 0 0 0
## 6 2020-01-31 30-39 years 0 0 0
## 7 2020-01-31 35-44 years 0 0 0
## 8 2020-01-31 40-49 years 0 0 0
## 9 2020-01-31 45-54 years 0 0 0
## 10 2020-01-31 5-14 years 0 0 0
## 11 2020-01-31 50-64 years 0 0 0
## 12 2020-01-31 55-64 years 0 0 0
## 13 2020-01-31 65-74 years 0 0 0
## 14 2020-01-31 75-84 years 0 0 0
## 15 2020-01-31 85 years and over 0 0 0
## 16 2020-01-31 All Ages 0 0 0
## 17 2020-01-31 Under 1 year 0 0 0
## 18 2020-02-29 0-17 years 0 0 0
## 19 2020-02-29 1-4 years 0 0 0
## 20 2020-02-29 15-24 years 0 0 0
# solo los totales de todas las edades por mes
covid_sex <- filter(covid_sex, age == "All Ages")
covid_sex
## # A tibble: 18 x 5
## date age `All Sexes` Female Male
## <date> <chr> <dbl> <dbl> <dbl>
## 1 2020-01-31 All Ages 0 0 0
## 2 2020-02-29 All Ages 0 0 0
## 3 2020-03-31 All Ages 21 10 11
## 4 2020-04-30 All Ages 78 31 47
## 5 2020-05-31 All Ages 35 15 20
## 6 2020-06-30 All Ages 16 NA 13
## 7 2020-07-31 All Ages 91 27 64
## 8 2020-08-31 All Ages 197 84 113
## 9 2020-09-30 All Ages 233 94 139
## 10 2020-10-31 All Ages 173 79 94
## 11 2020-11-30 All Ages 342 144 198
## 12 2020-12-31 All Ages 436 179 257
## 13 2021-01-31 All Ages 244 121 123
## 14 2021-02-28 All Ages 131 62 69
## 15 2021-03-31 All Ages 68 37 31
## 16 2021-04-30 All Ages 195 84 111
## 17 2021-05-31 All Ages 170 73 97
## 18 2021-06-12 All Ages NA 0 NA
Una vez realizados los procedimientos anteriores, podemos estar interesado/as en usar el tibble final en un análisis en otro proyecto o en otro programa. Usando la función write_csv podemos crear un archivo .csv.
# vamos a guardar en un archivo el tibble covid_sex
write_csv(covid_sex, file = "data/covid-sex.csv")