Tracking the "flattening" of the curve during the Covid19 ("Coronavirus") pandemic. A visualization proposal.
ESPAÑOL: Este projecto inició el 21 de marzo de 2020. Originalmente fue publicado en Google Sheets {as Colour tracking} y ahora lo presento en D3.js. Esta versión está disponible en GitHub, se ve mucho mejor y es mucho más rápida de ver y cargar. Espero que les guste y les sea útil. Los detallos los encuentran debajo de la gráfica.
ENGLISH: This project started on the 21st of March, 2020. Originally published in Google Sheets {as Colour tracking}, now a D3.js version is available on GitHub. It looks nicer and is much faster and efficient. I hope you like it and find it useful. Details below the heatmap.
¿Cómo funciona? / How does it work?
SPANISH "Rastreo de colores" presenta los casos registrados día a día para producir una matriz graduada o mapa de calor, similar a un mapa de ADN. Esta gráfica ayudar a visualizar los datos registrados en todo el mundo de un vistazo. Los datos se obtienen de JHU - CSSEGISandData / COVID-19, pero han sido pre-procesados usando Google Sheets. La página de acumulación, análisis y procesamiento de datos preliminar es esta => Track Covid-19 Pandemic curve Se utilizó un nuevo archivo para procesar de forma recurrente los datos en forma de matriz al formato lista. Esa tabla, está disponible aquí caseslistCovidMonthlyUpdate La tabla se actualizará en GitHub cada mes, este ejercicio maneja la tabla con corte al 20 de septiembre de 2020. En la figura de abajo se puede ver el cambio de de una plataforma a otra. Hay más dinamismo, más rapidez tanto para visualizar los datos como para cargarlo, se mejoró la visualización de los datos y se agregó un ventana emergente informativa para saber con precisión cuántos casos se reportaron en tal o cual día en un país determinado. Cualquier propuesta de mejora a la gráfica, al código o a la forma de visualizar los datos es bienvenida. Todos los datos son abiertos. ENGLISH "Colour tracking" presents the cases in a day-by-day fashion to produce a shading matrix or heatmap, similar to a DNA heatmap. It helps to visualize all recorded cases in the world at a glance. A new file was used to process new data iteratively such that array data is transformed into a list. This table is available here: caseslistCovidMonthlyUpdate The table will be updated in GitHub every month. This exercise uses a table with dates updated until the 20th of September. In the figure below it is shown the change from one platform to the other. There is more dynamism, more speed either to visualize data or to load it. Also, it was improved data visualization a tooltip was added to let you know with precision how many cases were reported at any single day per country. Any improvement proposal to the chart, to the code or to the way we could visualize data is welcome. All the information is open.
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Load d3.js --> | |
<script src="https://d3js.org/d3.v4.js"></script> | |
<!-- Create a div where the graph will take place --> | |
<div id="my_dataviz"></div> | |
<!-- Load color palettes --> | |
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> | |
<script> | |
// set the dimensions and margins of the graph | |
var margin = {top: 90, right: 100, bottom: 10, left: 100}, | |
width = 2900 - margin.left - margin.right, | |
height = 600 - margin.top - margin.bottom; | |
// append the svg object to the body of the page | |
var svg = d3.select("#my_dataviz") | |
.append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", | |
"translate(" + margin.left + "," + margin.top + ")"); | |
//Read the data | |
d3.csv("https://raw.githubusercontent.com/ishibaro/dataviz/master/HeatMapcovid19/csv_heatmap_covid19/caseslistCovidMonthlyUpdate28Diciembre2020.csv", | |
function(data) { | |
// Labels of row and columns -> unique identifier of the column called 'group' and 'variable' | |
// This allows to produce a heatmap a matrix of squares. | |
var myGroups = d3.map(data, function(d){return d.country;}).keys() | |
var myVars = d3.map(data, function(d){return d.date;}).keys() | |
// Build X scales and axis: | |
var x = d3.scaleBand() | |
.range([ 0, width ]) | |
.domain(myGroups) | |
.padding(0.02); | |
svg.append("g") | |
.style("font-size", 8.1) | |
.style("font-style", "italic") | |
.style("font-weight", "bold") | |
.style("font-family", "Saira") | |
.attr("text-decoration","underline") | |
.attr("transform", "translate(0," + height - margin.top +")") | |
.call(d3.axisTop(x).tickSize(1.8)) | |
.selectAll("text") | |
.attr("y", -5.2) | |
.attr("x", 0.25) | |
.attr("dy", ".35em") | |
.attr("transform", "rotate(-40)") | |
.style("text-anchor", "start") | |
.style("fill", "black") | |
.select(".domain").remove() | |
// Build Y scales and axis: | |
var y = d3.scaleBand() | |
.range([ 0, height]) | |
.domain(myVars) | |
.padding(0.01); | |
svg.append("g") | |
.style("font-size", 0) | |
.call(d3.axisLeft(y).tickSize(0)) | |
.select(".domain").remove() | |
// Build color scale | |
var myColor = d3.scaleSequential() | |
.interpolator(d3.interpolateYlOrRd) | |
.domain([1,100]) | |
// create a tooltip | |
var tooltip = d3.select("#my_dataviz") | |
.append("div") | |
.style("position", "absolute") | |
.style("visibility", "hidden") | |
.style("background-color", "azure") | |
.style("border", "solid") | |
.style("font-weight", "condensed") | |
.style("border-width", "1px") | |
.style("border-radius", "3px") | |
.style("padding", "2px") | |
.style("width", "115px") | |
.style("font-weight", "bold") | |
.style("font-size", 1) | |
.style("font-family", "Saira Condensed"); | |
// add the squares | |
svg.selectAll() | |
.data(data, function(d) {return d.country+':'+d.date;}) | |
.enter() | |
.append("rect") | |
.attr("x", function(d) { return x(d.country) }) | |
.attr("y", function(d) { return y(d.date) }) | |
.attr("rx", 1) | |
.attr("ry", 2) | |
.attr("width", x.bandwidth() ) | |
.attr("height", y.bandwidth() ) | |
.style("fill", function(d) { return myColor(d.value)} ) | |
.style("stroke-width", 0.5) | |
.style("stroke", "none") | |
.style("opacity", 0.55) | |
.on("mouseover", function(d){return tooltip.style("visibility", "visible").style("stroke-width", 1);}) | |
.on("mousemove", function(d){return tooltip.html(d.country + "<br>Cases: "+ d.value + "<br>Date: " + d.date).style("top", (event.pageY+22)+"px").style("left",(event.pageX)+"px");}) | |
.on("mouseout", function(d){return tooltip.style("visibility", "hidden");}); | |
}) | |
// Add title to graph | |
svg.append("text") | |
.attr("x", 0) | |
.attr("y", -75) | |
.attr("text-anchor", "left") | |
.style("font-size", "22px") | |
.style("font-size", 17) | |
.style("font-weight", "bold") | |
.style("font-style", "italic") | |
.style("font-family", "Aldrich") | |
.text("Track Covid-19 heatmap"); | |
// Add subtitle to graph | |
svg.append("text") | |
.attr("x", 0) | |
.attr("y", -540) | |
.attr("text-anchor", "left") | |
.style("font-size", "14px") | |
.style("fill", "grey") | |
.style("max-width", 400) | |
.text("Covid-19, global development analysis using a heatmap."); | |
</script> | |
<script> | |
// auxiliary scale to use dates rather than strings | |
var margin = {top: 90, right: 100, bottom: 10, left: 100}, | |
width = 2900 - margin.left - margin.right, | |
height = 600 - margin.top - margin.bottom; | |
//Read the data - this way our dates are always updated and there is no need to update the domain | |
d3.csv("https://raw.githubusercontent.com/ishibaro/dataviz/master/HeatMapcovid19/csv_heatmap_covid19/caseslistCovidMonthlyUpdate28Diciembre2020.csv", | |
// You can use autotype. In this case I decided to assign types manually: | |
// This function will parse the dates as time and we will use it to build the Y axis | |
function(d){ | |
return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value } | |
}, | |
// Now I can use this dataset: | |
function(data) { | |
// Add Y axis | |
var y = d3.scaleTime() | |
.domain(d3.extent(data, function(d) { return d.date; })) | |
.range([ 0, height ]); | |
svg.append("g") | |
.call(d3.axisLeft(y)); | |
// Add the line | |
svg.append("path") | |
.datum(data) | |
.attr("fill", "none") | |
.attr("stroke", "steelblue") | |
.attr("stroke-width", 1.5) | |
.attr("d", d3.line() | |
.x(function(d) { return x(d.date) }) | |
.y(function(d) { return y(d.value) }) | |
) | |
}) | |
</script> |
Comentarios
Publicar un comentario
Sientete libre de opinar sobre el tema. Prometo no enojarme con tu comentario...jajajaja, bueno no se, depende...