keywords: Visualization, R coding, graphics, Covid-19, Peru.

Introducción

¡Hola! Estoy aprendiendo programación en R con RStudio y este es mi primer proyecto de visualización donde muestro lo que he estado aprendiendo con respecto a la visualización de datos. Soy graduado en comunicación, tengo experiencia en producción cinematográfica, y me he sentido atraído por el campo de la analítica a través del área de visualización. Me sorprende la cantidad de información que puede contener una sola gráfica. Para mi, la visualización es como una buena película, te cuenta una historia y al mismo tiempo genera sensaciones y conversaciones.

Este proyecto trata sobre la evolución de la Covid-19 en Perú del 6 de marzo de 2020 al 31 de marzo de 2021. Perú, ubicado en América del Sur, tiene una población de 33 millones de personas y tres regiones geográficas distintas: Costa oeste desértica, Región central andina de montaña alta y la Amazonía peruana, que se extiende desde la cadena oriental de los Andes, a la selva baja de la Cuenca del Amazonas. Para más información sobre Perú haz click aquí

Los datos, presentados a nivel nacional, corresponden al número acumulado de casos en los informes diarios de; a) casos confirmados, b) casos recuperados, y c) número de muertes.

Desde el 15 de marzo de 2020, Perú ha estado bajo una serie de restricciones que se relajaron a medida que disminuía el número de casos; o se endurecián, según el número de casos comenzó a aumentar en respuesta al avance de la Covid-19 debido a una combinación de condiciones ambientales, capacidad hospitalaria y respuestas del comportamiento humano a las restricciones continuas que afectaron principalmente las interacciones sociales y económicas. Un impulsor importante del aumento temprano de personas afectadas por este virus es la necesidad de un gran segmento de la población del Perú de seguir trabajando durante la pandemia en trabajos con salarios muy bajos, lo que les imposibilitó seguir las regulaciones del gobierno de “quedarse en casa”.

Mis objetivos de visualización son graficar cada serie acumulada en un solo gráfico, graficar cada serie de casos diarios individuales en un gráfico interactivo individual, y obtener estos cuatro gráficos en una sola gráfica final manteniendo la interactividad de los gráficos de casos individuales y acumulados. No hace falta decir que he aprendido mucho al completar estas tareas y disfruté cada paso de mi curva de aprendizaje.

Data

Los archivos de datos (datasets) se descargaron del repositorio de github de CSSE-John Hopkins University . Cada dataset contiene información a nivel nacional, 274 filas para los países en los datasets de casos confirmados y de muertes; y 259 filas en el dataset de casos recuperados; cada día corresponde a una columna, para un total de 439 columnas. La fecha en formato mm-dd-yyyy da nombre a cada columna. Cada país corresponde a una fila, excepto Australia, Canadá, China, Dinamarca, Francia, Países Bajos y Reino Unido, que presentan información a nivel provincial. El último día de acceso al repositorio fue el 31/03/2021.

Los datasets descargados estaban en formato ancho y tienen la cadena de caracteres ‘X.’ delante de la fecha que da nombre a las columnas. Use el comando base::substring para eliminar estas cadenas. Adicionalmente, en cada dataset, agregué, con el comando dplyr::inner_join, la variable continents, que corresponde al continente en el que se encuentra cada país y region que corresponde a la región geopolítica de cada país.

Luego, convertí cada dataset de un formato ancho a un formato largo usando el comando tidyr::pivot_longer. Como resultado, los conjuntos de datos finales tienen 5 columnas y 67080 filas. Las columnas corresponden a Country.Region(lista de países), continent(lista de continentes), region(lista de regiones), dates(fechas), y confirmed(para la dataset de los casos confirmados), o recovered(para la dataset de los casos recuperados), o deaths(para el dataset de número de muertes). Finalmente, la variable dates fue convertida (de formato ‘integer’) a formato de fechas con el comando lubridate::mdy.

Especificaciones Técnicas

Este proyecto se realizó con:

R Packages

library(readxl)
library(tidyverse)
library(magrittr)
library(lubridate)
library(dplyr)
library(xts)
library(tsibble)
library(slider)
library(dygraphs)
library(plotly)
library(manipulateWidget)
library(knitr)

Leer la dataset de los casos de Confirmados acumulados (confirmed)

confirmed <- read.csv("/Users/marcoarellano/Desktop/DATA SCIENCE/COVID 19/03.31.2021/DATA/time_series_covid19_confirmed_global.csv")
n_colsc <- dim(confirmed)[2]
n_rowsc <- dim(confirmed)[1]
names(confirmed)[5:n_colsc] <- substring(names(confirmed)[5:n_colsc],2)
tail(confirmed[, 1:6])
##     Province.State     Country.Region       Lat      Long 1.22.20 1.23.20
## 269                         Venezuela   6.42380 -66.58970       0       0
## 270                           Vietnam  14.05832 108.27720       0       2
## 271                West Bank and Gaza  31.95220  35.23320       0       0
## 272                             Yemen  15.55273  48.51639       0       0
## 273                            Zambia -13.13390  27.84933       0       0
## 274                          Zimbabwe -19.01544  29.15486       0       0

confirmed dataset tiene 274 filas y 439 columnas.

Leer la dataset de los casos de Recuperados acumulados (recovered)

recovered <- read.csv("/Users/marcoarellano/Desktop/DATA SCIENCE/COVID 19/03.31.2021/DATA/time_series_covid19_recovered_global.csv")
n_colsr <- dim(recovered)[2]
n_rowsr <- dim(recovered)[1]
names(recovered)[5:n_colsr] <- substring(names(recovered)[5:n_colsr],2)
tail(recovered[, 1:6])
##     Province.State     Country.Region       Lat      Long 1.22.20 1.23.20
## 254                         Venezuela   6.42380 -66.58970       0       0
## 255                           Vietnam  14.05832 108.27720       0       0
## 256                West Bank and Gaza  31.95220  35.23320       0       0
## 257                             Yemen  15.55273  48.51639       0       0
## 258                            Zambia -13.13390  27.84933       0       0
## 259                          Zimbabwe -19.01544  29.15486       0       0

recovered dataset tiene 259 filas y 439 columnas.

Leer la dataset de Muertes acumuladas (deaths)

deaths <- read.csv("/Users/marcoarellano/Desktop/DATA SCIENCE/COVID 19/03.31.2021/DATA/time_series_covid19_deaths_global.csv")
n_colsd <- dim(deaths)[2]
n_rowsd <- dim(deaths)[1]
names(deaths)[5:n_colsd] <- substring(names(deaths)[5:n_colsd],2)
tail(deaths[, 1:6])
##     Province.State     Country.Region       Lat      Long 1.22.20 1.23.20
## 269                         Venezuela   6.42380 -66.58970       0       0
## 270                           Vietnam  14.05832 108.27720       0       0
## 271                West Bank and Gaza  31.95220  35.23320       0       0
## 272                             Yemen  15.55273  48.51639       0       0
## 273                            Zambia -13.13390  27.84933       0       0
## 274                          Zimbabwe -19.01544  29.15486       0       0

deaths dataset tiene 274 filas and 439 columnas.

Leer la dataset de los Continentes y la lista de los paises (continents)

continents <- read_excel("~/Desktop/DATA SCIENCE/COVID 19/03.31.2021/DATA/continents_Corrected.xlsx")
head(continents)
## # A tibble: 6 x 3
##   Country.Region      continent                          region         
##   <chr>               <chr>                              <chr>          
## 1 Afghanistan         Asia                               Southern Asia  
## 2 Albania             Eastern Europe                     Southern Europe
## 3 Algeria             Africa                             Northern Africa
## 4 Andorra             Western Europe and other States    Northern Europe
## 5 Angola              Africa                             Middle Africa  
## 6 Antigua and Barbuda Latin America and Caribbean States Caribbean

Aquí creo el formato largo para cada dataset con los siguientes pasos:

  1. Agrego la variable continents al conjunto de datos, usando dplyr::inner_join ()
  2. Uso dplyr::pivot_longer para el cambio de tener cada fecha como una columna, a tener cada fecha como una fila, agrupadas por cada país y provincia donde sea necesario.
  3. Defino la columna dates como Variable de clase Date.
  4. Para uniformizar en los casos en los que hay más de una fila por país,
    a) Agrupo cada conjunto de datos por Country.Region, continent, region, dates,
    b) Obtengo los valores acumulados de confirmed(confirmados) o recovered(recuperados), o deaths(muertes),
  5. Cancelo la agrupación.

Crear la version larga para casos confirmados acumulados (confirmed_long)

confirmed_long <- confirmed %>%
  inner_join(continents, by = "Country.Region") %>%
  pivot_longer (
    cols = !c(Province.State, Country.Region, Lat, Long, continent, region),
    names_to = c("dates"),
    values_to = "confirmed") %>%
  mutate(dates = mdy(dates)) %>%
  group_by(Country.Region, continent, region, dates) %>%
  summarise(confirmed = sum(confirmed)) %>%
  ungroup()
n_colscl <- dim(confirmed_long)[2]
n_rowscl <- dim(confirmed_long)[1]
tail(confirmed_long)
## # A tibble: 6 x 5
##   Country.Region continent region         dates      confirmed
##   <chr>          <chr>     <chr>          <date>         <int>
## 1 Zimbabwe       Africa    Eastern Africa 2021-03-26     36805
## 2 Zimbabwe       Africa    Eastern Africa 2021-03-27     36818
## 3 Zimbabwe       Africa    Eastern Africa 2021-03-28     36822
## 4 Zimbabwe       Africa    Eastern Africa 2021-03-29     36839
## 5 Zimbabwe       Africa    Eastern Africa 2021-03-30     36839
## 6 Zimbabwe       Africa    Eastern Africa 2021-03-31     36882

confirmed_long dataset tiene 67860 filas and 5 columnas.

Crear la version larga para casos recuperados acumulados (recovered_long)

recovered_long <- recovered %>%
  inner_join(continents, by = "Country.Region") %>%
  pivot_longer (
    cols = !c(Province.State, Country.Region, Lat, Long, continent, region),
    names_to = c("dates"),
    values_to = "recovered") %>%
  mutate(dates = mdy(dates))%>%
  group_by(Country.Region, continent, region, dates) %>%
  summarise(recovered = sum(recovered)) %>%
  ungroup()
n_colsrl <- dim(recovered_long)[2]
n_rowsrl <- dim(recovered_long)[1]
tail(recovered_long)
## # A tibble: 6 x 5
##   Country.Region continent region         dates      recovered
##   <chr>          <chr>     <chr>          <date>         <int>
## 1 Zimbabwe       Africa    Eastern Africa 2021-03-26     34572
## 2 Zimbabwe       Africa    Eastern Africa 2021-03-27     34575
## 3 Zimbabwe       Africa    Eastern Africa 2021-03-28     34603
## 4 Zimbabwe       Africa    Eastern Africa 2021-03-29     34617
## 5 Zimbabwe       Africa    Eastern Africa 2021-03-30     34617
## 6 Zimbabwe       Africa    Eastern Africa 2021-03-31     34686

recovered_long dataset tiene 67860 filas and 5 columnas.

Crear la version larga para fallecimientos confirmados acumulados (deaths_long)

deaths_long <- deaths %>%
  inner_join(continents, by = "Country.Region") %>%
  pivot_longer (
    cols = !c(Province.State, Country.Region, Lat, Long, continent, region),
    names_to = c("dates"),
    values_to = "deaths") %>%
  mutate(dates = mdy(dates)) %>%
  group_by(Country.Region, continent, region, dates) %>%
  summarise(deaths= sum(deaths)) %>%
  ungroup()
n_colsdl <- dim(deaths_long)[2]
n_rowsdl <- dim(deaths_long)[1]
tail(deaths_long)
## # A tibble: 6 x 5
##   Country.Region continent region         dates      deaths
##   <chr>          <chr>     <chr>          <date>      <int>
## 1 Zimbabwe       Africa    Eastern Africa 2021-03-26   1518
## 2 Zimbabwe       Africa    Eastern Africa 2021-03-27   1519
## 3 Zimbabwe       Africa    Eastern Africa 2021-03-28   1520
## 4 Zimbabwe       Africa    Eastern Africa 2021-03-29   1520
## 5 Zimbabwe       Africa    Eastern Africa 2021-03-30   1520
## 6 Zimbabwe       Africa    Eastern Africa 2021-03-31   1523

deaths_long dataset tiene 67860 filas y 5 columnas.

A continuación, creo una nueva columna que corresponde al número de casos diarios en cada conjunto de datos.

Los casos diarios se logran restando los casos del día (j-1) al día (j), la diferencia nos da el aumento de casos en un solo día. Para lograr esto, utilizo el comando dplyr::lag que permite encontrar el número de casos del día anterior. El uso de la opción lag () default = 0 , significa que el valor de lag para la primera observación será el mismo que el valor observado para ese día.

  1. El pedido se realiza secuencialmente desde la primera fecha, 22/01/2020, hasta la fecha final, 31/03/2021.
  2. Agrupo las filas por Country.Region(países).
  3. Creo las variables confirmed_dailycases(confirmados diarios), o recovered_dailycases(recuperados diarios), o deaths_dailycases(muertes diarias).
  4. Cancelo la agrupación dentro de cada dataset.

Crear la variable casos diarios confirmados (confirmed_dailycases)

confirmed_long <- confirmed_long %>%
  arrange(dates) %>%
  group_by(Country.Region) %>%
  mutate(confirmed_dailycases = confirmed - lag(confirmed, default = 0)) %>%
  ungroup()
head(confirmed_long)
## # A tibble: 6 x 6
##   Country.Region continent       region    dates      confirmed confirmed_daily…
##   <chr>          <chr>           <chr>     <date>         <int>            <dbl>
## 1 Afghanistan    Asia            Southern… 2020-01-22         0                0
## 2 Albania        Eastern Europe  Southern… 2020-01-22         0                0
## 3 Algeria        Africa          Northern… 2020-01-22         0                0
## 4 Andorra        Western Europe… Northern… 2020-01-22         0                0
## 5 Angola         Africa          Middle A… 2020-01-22         0                0
## 6 Argentina      Latin America … South Am… 2020-01-22         0                0

Crear la variable casos diarios recuperados (recovered_dailycases)

recovered_long <- recovered_long %>%
  arrange(dates) %>%
  group_by(Country.Region) %>%
  mutate(recovered_dailycases = recovered - lag(recovered, default = 0)) %>%
  ungroup()
head(recovered_long)
## # A tibble: 6 x 6
##   Country.Region continent       region    dates      recovered recovered_daily…
##   <chr>          <chr>           <chr>     <date>         <int>            <dbl>
## 1 Afghanistan    Asia            Southern… 2020-01-22         0                0
## 2 Albania        Eastern Europe  Southern… 2020-01-22         0                0
## 3 Algeria        Africa          Northern… 2020-01-22         0                0
## 4 Andorra        Western Europe… Northern… 2020-01-22         0                0
## 5 Angola         Africa          Middle A… 2020-01-22         0                0
## 6 Argentina      Latin America … South Am… 2020-01-22         0                0

Crear la variable fallecimientos diarios (deaths_dailycases)

deaths_long <- deaths_long %>%
  arrange(dates) %>%
  group_by(Country.Region) %>%
  mutate(deaths_dailycases = deaths - lag(deaths, default = 0)) %>%
  ungroup()
head(deaths_long)
## # A tibble: 6 x 6
##   Country.Region continent          region    dates      deaths deaths_dailycas…
##   <chr>          <chr>              <chr>     <date>      <int>            <dbl>
## 1 Afghanistan    Asia               Southern… 2020-01-22      0                0
## 2 Albania        Eastern Europe     Southern… 2020-01-22      0                0
## 3 Algeria        Africa             Northern… 2020-01-22      0                0
## 4 Andorra        Western Europe an… Northern… 2020-01-22      0                0
## 5 Angola         Africa             Middle A… 2020-01-22      0                0
## 6 Argentina      Latin America and… South Am… 2020-01-22      0                0

Aquí selecciono datos de mi país, Perú, siguiendo los pasos:

  1. Utilizo dplyr::filter para seleccionar datos de Perú en cada dataset.
  2. Selecciono las variables que se incluirán en cada dataset de Perú: Peru_confirmed , Peru_recovered , Peru_deaths.
  3. Eliminé la columna Country.Region(países) porque los tres conjuntos de datos se refieren a Perú.
  4. Utilizo dplyr::full_join para crear un único conjunto de datos con las tres series: confirmed(confirmados), recovered(recuperadas) y deaths (muertes). La variable dates(fechas) se utiliza para unir los tres datasets de Perú.
  5. Finalmente, creo una nueva variable, deaths_100k, que corresponde a (#muertes/32625948)10^5), ya que la población de Perú para marzo de 2021 se estima en 32 625 948 millones.
Peru_confirmed <- confirmed_long %>%
  filter(Country.Region %in% "Peru") %>%
  select(Country.Region, dates, confirmed, confirmed_dailycases)
Peru_confirmed <- Peru_confirmed[,-c(1)]

Peru_recovered <- recovered_long %>%
  filter(Country.Region %in% "Peru") %>%
  select(Country.Region, dates, recovered, recovered_dailycases)
Peru_recovered <- Peru_recovered[,-c(1)]

Peru_deaths <- deaths_long %>%
  filter(Country.Region %in% "Peru") %>%
  select(Country.Region, dates, deaths, deaths_dailycases)
Peru_deaths <- Peru_deaths[,-c(1)]

Combinar los tres datasets en el nuevo dataset Peru_global

Peru_global <- Peru_confirmed %>%
  full_join(Peru_recovered, by = "dates") %>%
  full_join(Peru_deaths, by = "dates") %>%
  mutate(deaths_100k = ceiling((deaths/32625948)*10^5))
n_colspg <- dim(Peru_global)[2]
n_rowspg <- dim(Peru_global)[1]
tail(Peru_global)
## # A tibble: 6 x 8
##   dates      confirmed confirmed_daily… recovered recovered_daily… deaths
##   <date>         <int>            <dbl>     <int>            <dbl>  <int>
## 1 2021-03-26   1512384            11919   1423259            16955  51032
## 2 2021-03-27   1520973             8589   1432450             9191  51238
## 3 2021-03-28   1529882             8909   1442405             9955  51469
## 4 2021-03-29   1533121             3239   1451112             8707  51635
## 5 2021-03-30   1533121                0   1451112                0  51635
## 6 2021-03-31   1548807            15686   1468457            17345  52008
## # … with 2 more variables: deaths_dailycases <dbl>, deaths_100k <dbl>

Peru_global dataset tiene 435 filas y 8 columnas.

A continuación, creo una nueva variable correspondiendo al promedio móvil de 7 días para cada una de las variables confirmed(confirmados), recovered(recuperados) y deaths(muertes) en el dataset Peru_global.

Primero, usando el comando tsibble::as_tsibble transformo el dataset Peru_global en un objeto de series de tiempo.

nr <- nrow(Peru_global)
Peru_global$rid <- seq(1, nr ,1)
Peru_global_ts <- as_tsibble(Peru_global, 
                             key = rid,
                             index = dates)

El promedio móvil de 7 días (7-day Rolling Average) toma siete valores consecutivos y calcula su promedio, este promedio se empareja con la fecha central del intervalo de 7 días, que corresponde a la cuarta fecha; el siguiente intervalo de 7 días se crea eliminando la fecha más temprana del intervalo y agregando la fecha siguiente después de la última fecha del intervalo.

Peru_global_ts <- Peru_global_ts %>% 
  filter_index("2020-03-06" ~ .) %>% 
  mutate(confirmed7_dailycases = slide_index_dbl(.i = dates,
                                                 .x = confirmed_dailycases,
                                                 .f = mean,
                                                 .before = 3,
                                                 .after= 3),
          recovered7_dailycases = slide_index_dbl(.i = dates,
                                                  .x = recovered_dailycases,
                                                  .f = mean,
                                                  .before = 3,
                                                  .after = 3),
         deaths7_dailycases = slide_index_dbl(.i = dates,
                                              .x = deaths_dailycases,
                                              .f = mean,
                                              .before = 3,
                                              .after = 3),
         confirmed7 = slide_index_dbl(.i = dates,
                                      .x = confirmed,
                                      .f = mean,
                                      .before = 3,
                                      .after = 3),
         recovered7 = slide_index_dbl(.i = dates,
                                      .x = recovered,
                                      .f = mean,
                                      .before = 3,
                                      .after = 3),
         deaths7 = slide_index_dbl(.i = dates,
                                   .x = deaths,
                                   .f = mean,
                                   .before = 3,
                                   .after = 3))

head(Peru_global_ts)
## # A tsibble: 6 x 15 [1D]
## # Key:       rid [6]
##   dates      confirmed confirmed_daily… recovered recovered_daily… deaths
##   <date>         <int>            <dbl>     <int>            <dbl>  <int>
## 1 2020-03-06         1                1         0                0      0
## 2 2020-03-07         1                0         0                0      0
## 3 2020-03-08         6                5         0                0      0
## 4 2020-03-09         7                1         0                0      0
## 5 2020-03-10        11                4         0                0      0
## 6 2020-03-11        11                0         0                0      0
## # … with 9 more variables: deaths_dailycases <dbl>, deaths_100k <dbl>,
## #   rid <dbl>, confirmed7_dailycases <dbl>, recovered7_dailycases <dbl>,
## #   deaths7_dailycases <dbl>, confirmed7 <dbl>, recovered7 <dbl>, deaths7 <dbl>

¡Ahora grafiquemos!

Utilizo la library dygraph para graficar una serie de tiempo interactiva para los casos diarios de confirmados(confirmed), recuperados(recovered) y muertes(deaths). Cada serie de tiempo cuenta con 2 variables: el número diario de casos y el promedio móvil de 7 días.

El gráfico interactivo permite ver con mayor detalle intervalos seleccionados de fechas.

El primer gráfico es para el número de casos confirmados diarios.

peru_int_confirmeddaily <- cbind(Peru_global_ts[c(1, 3, 10)])
peru_int_confirmeddaily$confirmed7_dailycases <- round(peru_int_confirmeddaily$confirmed7_dailycases, 0)
rownames( peru_int_confirmeddaily) <- as.POSIXlt( peru_int_confirmeddaily[, 1])
ts_peru_int_confirmeddaily <-  peru_int_confirmeddaily[, -1]
dygraph(ts_peru_int_confirmeddaily, 
        main = "Confirmed Covid-19 Daily cases") %>%
  dySeries("confirmed_dailycases", stepPlot = TRUE, 
           fillGraph = TRUE, color = "lightblue", label = "Confirmed Daily Cases") %>%
  dySeries("confirmed7_dailycases", drawPoints = TRUE, 
           pointShape = "square", color = "darkblue", label = "Rolling Avg 7") %>%
  dyRangeSelector(height = 20) %>%
  dyLegend(width = 300) 



El segundo gráfico corresponde al número diario de casos recuperados.

peru_int_recovereddaily <- cbind(Peru_global_ts[c(1, 5, 11)])
peru_int_recovereddaily$recovered7_dailycases <- round(peru_int_recovereddaily$recovered7_dailycases, 0)
rownames( peru_int_recovereddaily) <- as.POSIXlt( peru_int_recovereddaily[, 1])
ts_peru_int_recovereddaily <-  peru_int_recovereddaily[, -1]
dygraph(ts_peru_int_recovereddaily, 
        main = " Recovered Covid-19 Daily cases") %>%
  dySeries("recovered_dailycases", stepPlot = TRUE, 
           fillGraph = TRUE, color = "turquoise", label = "Recovered Daily Cases") %>%
  dySeries("recovered7_dailycases", drawPoints = TRUE, 
           pointShape = "circle", color = "green", label = "Rolling Avg 7") %>%
  dyRangeSelector(height = 20) %>%
  dyLegend(width = 300) 



El tercer gráfico es para el número de muertes diarias.

peru_int_deathsdaily <- cbind(Peru_global_ts[c(1, 7, 12)])
peru_int_deathsdaily$deaths7_dailycases <- round(peru_int_deathsdaily$deaths7_dailycases, 0)
rownames( peru_int_deathsdaily) <- as.POSIXlt( peru_int_deathsdaily[, 1])
ts_peru_int_deathsdaily <-  peru_int_deathsdaily[, -1]
dygraph(ts_peru_int_deathsdaily,
        main = "Covid-19 Daily Deaths") %>%
  dySeries("deaths_dailycases", stepPlot = TRUE, fillGraph = TRUE, 
           color = "orange", label = "Deaths Daily Cases") %>%
  dySeries("deaths7_dailycases", drawPoints = TRUE, pointShape = "square",
           color = "red", label = "Rolling Avg 7") %>%
  dyRangeSelector(height = 20) %>%
  dyLegend(width = 285) 



La library plotly se utiliza para crear el último gráfico. Para este gráfico usamos los valores acumulados y el promedio móvil de 7 días de nuestras 3 variables: confirmed(confirmados), recovered(recuperados) and deaths(muertes).

Este gráfico tiene 2 ejes Y. El eje Y de la izquierda corresponde a los valores acumulados de los casos confirmados y recuperados; por otro lado, el eje Y de la derecha, corresponde a los valores acumulados de las muertes. Consideré utilizar dos ejes Y porque los valores confirmados y recuperados tienen un rango similar, en contraste con los valores de muertes que tienen un rango menor. Por eso, para visualizar mejor la tendencia de la serie de fallecimientos, se decidió agregar el segundo eje Y.

plot_ly() %>%
  add_trace(x = ~Peru_global_ts$dates, y = ~ round(Peru_global_ts$confirmed7, 0), name = "Confirmed",  
            type = 'scatter', mode = 'lines', line = list(color = 'blue', size = 4),
            hoverinfo = "text",
            text = ~paste("Date: ", Peru_global_ts$dates,
                          "<br>",
                          "Confirmed: ", round(Peru_global_ts$confirmed7, 0))) %>%
  add_trace(x = ~Peru_global_ts$dates, y = ~round(Peru_global_ts$recovered7, 0), name = "Recovered",
            type = 'scatter', mode = 'lines', line = list(color = 'green', size = 4),
            hoverinfo = "text",
            text = ~paste("Date: ", Peru_global_ts$dates,
                          "<br>",
                          "Recovered: ", round(Peru_global_ts$recovered7, 0))) %>% 
  add_trace(x = ~Peru_global_ts$dates, y = ~round(Peru_global_ts$deaths7, 0), name = "Deaths", yaxis = "y2",
            type = 'scatter', mode = 'lines', line = list(color = 'red', size = 4),
            hoverinfo = "text",
            text = ~paste("Date: ",Peru_global_ts$dates,
                          "<br>",
                          "Deaths: ", round(Peru_global_ts$deaths7, 0))) %>% 
  layout( title = list(text ="7-day Rolling Average Cumulative Covid-19 cases Peru 2020-2021",
                       size = 10),
          yaxis2 = list(tickfont = list(color = "red"),
                        overlaying = "y",
                        side = "right",
                        title = "Cumulative Deaths",
                        showgrid = FALSE),
          xaxis = list(title = "Dates",
                       color = "black"),
          yaxis = list(tickangle = 0,
                      title = "Cumulative Confirmed and Recovered <br><br><br>",
                      standoff = 90,
                      showgrid = FALSE),
          legend = list(orientation = "h",   
                        xanchor = "center",  
                        x = 0.5,             
                        y = -0.2),
          autosize = T,
          margin = list(l = 100, r = 100, b = 100, t = 100, pad = 20)) 

Una vez que todos nuestros gráficos están terminados, los combino en una sola figura que consta de dos columnas; la columna de la izquierda tiene el gráfico de las series de tiempo de los casos acumulados combinados, y la columna de la derecha tiene tres gráficos individuales correspondientes a los casos diarios.

Uso el comando manipulateWidget::combineWidget. Este comando permite unir nuestros gráficos interactivos en una sola imagen de forma rápida y sencilla.

Primero, creo una función para combinar en un solo gráfico las tres series acumulativas.

cumulates_plotly <- function(id){plot_ly() %>%
  add_trace(x = ~Peru_global_ts$dates, y = ~ round(Peru_global_ts$confirmed7, 0), name = "Confirmed",  
            type = 'scatter', mode = 'lines', line = list(color = 'blue', size = 4),
            hoverinfo = "text",
            text = ~paste("Date: ", Peru_global_ts$dates,
                          "<br>",
                          "Confirmed: ", round(Peru_global_ts$confirmed7, 0))) %>%
  add_trace(x = ~Peru_global_ts$dates, y = ~round(Peru_global_ts$recovered7, 0), name = "Recovered",
            type = 'scatter', mode = 'lines', line = list(color = 'green', size = 4),
            hoverinfo = "text",
            text = ~paste("Date: ", Peru_global_ts$dates,
                          "<br>",
                          "Recovered: ", round(Peru_global_ts$recovered7, 0))) %>% 
  add_trace(x = ~Peru_global_ts$dates, y = ~round(Peru_global_ts$deaths7, 0), name = "Deaths", yaxis = "y2",
            type = 'scatter', mode = 'lines', line = list(color = 'red', size = 4),
            hoverinfo = "text",
            text = ~paste("Date: ", Peru_global_ts$dates,
                          "<br>",
                          "Deaths: ", round(Peru_global_ts$deaths7, 0))) %>% 
  layout( title = list(text = "7-day Rolling Average Cumulative Covid-19 cases Peru 2020-2021",
                       size = 10),
          yaxis2 = list(tickfont = list(color = "red"),
                        overlaying = "y",
                        side = "right",
                        title = "Cumulative Deaths",
                        showgrid= FALSE),
          xaxis = list(title = "Dates",
                       color = "black"),
          yaxis = list(tickangle =0,
                      title = "Cumulative Confirmed and Recovered <br><br><br>",
                      standoff = 90,
                      showgrid = FALSE),
          legend = list(orientation = "h",   
                        xanchor = "center",  
                        x = 0.5,             
                        y = -0.2),
          autosize = T,
          margin = list(l = 100, r = 100, b = 100, t = 100, pad = 20))}

En segundo lugar, creo una función para definir cada componente de la columna de la derecha en la figura final.

c1 <-function(id){dygraph(ts_peru_int_confirmeddaily, 
        main = "Confirmed Covid-19 Daily cases") %>%
  dySeries("confirmed_dailycases", stepPlot = TRUE, 
           fillGraph = TRUE, color = "lightblue", label = "Confirmed Daily Cases") %>%
  dySeries("confirmed7_dailycases", drawPoints = TRUE, 
           pointShape = "square", color = "darkblue", label = "Rolling Avg 7") %>%
  dyRangeSelector(height = 20) %>%
  dyLegend(width = 300)}

r1<-function(id){dygraph(ts_peru_int_recovereddaily, 
        main = " Recovered Covid-19 Daily cases") %>%
  dySeries("recovered_dailycases", stepPlot = TRUE, 
           fillGraph = TRUE, color = "turquoise", label = "Recovered Daily Cases") %>%
  dySeries("recovered7_dailycases", drawPoints = TRUE, 
           pointShape = "circle", color = "green", label = "Rolling Avg 7") %>%
  dyRangeSelector(height = 20) %>%
  dyLegend(width = 300)}

d1<-function(id){dygraph(ts_peru_int_deathsdaily,
        main = "Covid-19 Daily Deaths") %>%
  dySeries("deaths_dailycases", stepPlot = TRUE, fillGraph = TRUE, 
           color = "orange", label = "Deaths Daily Cases") %>%
  dySeries("deaths7_dailycases", drawPoints = TRUE, pointShape = "square",
           color = "red", label = "Rolling Avg 7") %>%
  dyRangeSelector(height = 20) %>%
  dyLegend(width = 285)}

Para concluir, utilizo combineWidget para organizar los gráficos en el gráfico final. Además, creo la función write_alt_text para agregar un texto alternativo al gráfico.

write_alt_text <- function(
  chart_type, 
  type_of_data, 
  reason, 
  source){glue::glue(
    "{chart_type} de {type_of_data} donde {reason} <br> \n\nFuente: {source}")}
combineWidgets(
  ncol = 2, colsize = c(2,1),
  cumulates_plotly(1),
  title = "Gráficas Interactivas de las Series de Tiempo Covid-19 Perú",
  footer = write_alt_text(
  "Serie de Tiempo", 
  "Casos de confirmados, recuperados y muertes por Covid-19 en el Perú", 
  "la información sobre la evolución del Covid-19 es necesaria.", 
  "MINSA-Peru/ CSSE-John Hopkins University.<br>Hecho por Marco Arellano B. Twitter: marellanob93, Github: marellanob") ,
  combineWidgets(
    ncol = 1,
    c1(2),
    r1(3),
    d1(4)))