Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving average chart #51

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
43 changes: 43 additions & 0 deletions src/components/DeathRateChart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/** @jsx jsx */
import { jsx } from "theme-ui";
import { useStaticQuery, graphql } from "gatsby";
import { useTranslation } from "react-i18next";

import calculateMovingAverageSeries from "../util/movingAverage";

import StatChart from "../components/StatChart";
import Colors from "../constants/Colors";

const DeathRateChart = () => {
const data = useStaticQuery(graphql`
{
allDataJson(filter: { exitus: { gt: 3 } }) {
nodes {
data
exitus
}
}
}
`);

let nodes = data.allDataJson.nodes;
console.log(nodes)

// moving average series
let movingAverageSeries = calculateMovingAverageSeries(nodes, 7);
console.log(movingAverageSeries)

const { t } = useTranslation();
return (
// <div></div>
<StatChart
title={t("morts_per_dia_title")}
data={movingAverageSeries}
yKey="mitjana_mobil"
xKey="data"
color={Colors.primary}
/>
);
};

export default DeathRateChart;
6 changes: 6 additions & 0 deletions src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import StackedCases from "../charts/StackedCases";

import StatChart from "../components/StatChart";
import StatChartComparison from "../components/StatChartComparison";
import DeathRateChart from "../components/DeathRateChart";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Overview from "../components/Overview";
Expand Down Expand Up @@ -61,7 +62,9 @@ const Index = () => {

let nodes = data.allDataJson.nodes.sort((a, b) => a.timestamp - b.timestamp);
const currentNode = last(nodes);

const { t } = useTranslation();

return (
<div
sx={{
Expand Down Expand Up @@ -145,6 +148,9 @@ const Index = () => {
color={Colors.tertiary}
/>
</Grid>
<Grid columns={[1, 2]} gap={4} py={3} width={300}>
<DeathRateChart />
</Grid>
</Container>
</main>
<Footer />
Expand Down
4 changes: 4 additions & 0 deletions src/util/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ const resources = {
poblacio: "Población",
uvac_actius: "Activos UVAC",
act_dades: "Último registro",
morts_per_dia_title:"Fallecidos-día por millón de habitantes",
mitjana_mobil:"Media móvil de 7 días (desde el primer día con tres o más fallecidos acumulados)",
},
},
ca: {
Expand Down Expand Up @@ -82,6 +84,8 @@ const resources = {
poblacio: "Población",
uvac_actius: "Actius UVAC",
act_dades: "Darrer registre",
morts_per_dia_title:"Morts-día per milió d'habitants",
mitjana_mobil:"Mitjana mòbil de 7 dies (des del primer dia amb 3 exitus o més acumulats)",
},
},
};
Expand Down
56 changes: 56 additions & 0 deletions src/util/movingAverage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import last from "lodash/last";

/**
* @desc infers a series of daily deaths count from a cumulative series of deaths.
* @param Array $dailyCumulativeCountsArray - an array of objects that represents a
* deaths time series.
* @return Array - a series of daily deaths count .
*/
const calculateDailyDeathsCountSeries = (dailyCumulativeCountsArray) => {
//first cumulative array element should be taken as is
let dailyCountsArraySeries = [
{
deaths_per_date: dailyCumulativeCountsArray[0].exitus,
data: dailyCumulativeCountsArray[0].data}
]
//first cumulative array element should be processed
for (let i = 1; i < dailyCumulativeCountsArray.length; i++) {
dailyCountsArraySeries.push(
{
deaths_per_date: (dailyCumulativeCountsArray[i].exitus - dailyCumulativeCountsArray[i-1].exitus),
data: dailyCumulativeCountsArray[i].data
}
);
}
return dailyCountsArraySeries
}

/**
* @desc calculates a moving average series for a given time window.
* @param Array $dailyCountsArray - an array of objects that represents a
* deaths time series.
* @param window $int - the number of days that should be considered to calculate the moving average.
* @return Array - a series of moving averages per day.
*/

const calculateMovingAverageSeries = (nodes, window) => {
let resultingSeries = [];
let dailyCountsArraySeries = calculateDailyDeathsCountSeries(nodes)
for (let i = 0; i < dailyCountsArraySeries.length + 1 - window; i++) {
let dataInWindow = dailyCountsArraySeries.slice(i, i + window);
let lastDateInWindow = last(dataInWindow).data
// 1.198.576 inhabitants in Balearic Islands
// Source INE, July 2019 data: https://www.ine.es/jaxiT3/Datos.htm?t=9681#!tabs-mapa
// to calculate deaths per million inhabitants we apply a 1/1.198576 factor
let deathsMillionPerDateInWindow = dataInWindow.map((item) => {
return (item.deaths_per_date/1.198576); });
let sum = deathsMillionPerDateInWindow.reduce(
(previous, current) => (current += previous)
);
let avg = (sum / deathsMillionPerDateInWindow.length).toFixed(2);
resultingSeries.push({mitjana_mobil: avg, data: lastDateInWindow});
}
return resultingSeries;
};

export default calculateMovingAverageSeries