Initial work on health conditions report.
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -59,6 +59,7 @@ declare module 'vue' {
|
||||
TrendRiskAge: typeof import('./src/components/charts/risk/age/TrendRiskAge.vue')['default']
|
||||
TrendRiskCasesAge: typeof import('./src/components/charts/risk/age/TrendRiskCasesAge.vue')['default']
|
||||
'TrendRiskCasesAge copy': typeof import('./src/components/charts/risk/age/TrendRiskCasesAge copy.vue')['default']
|
||||
TrendRiskHealthConditions: typeof import('./src/components/charts/risk/health-conditions/TrendRiskHealthConditions.vue')['default']
|
||||
TrendTotalCases: typeof import('./src/components/charts/overall/cases/TrendTotalCases.vue')['default']
|
||||
TrendTotalCasesPerCapita: typeof import('./src/components/charts/overall/cases/TrendTotalCasesPerCapita.vue')['default']
|
||||
TrendTotalDeaths: typeof import('./src/components/charts/overall/deaths/TrendTotalDeaths.vue')['default']
|
||||
|
||||
@@ -9,6 +9,7 @@ import OverallHospitalizations from './parser/overall/hospitalizations.js'
|
||||
import OverallDeaths from './parser/overall/deaths.js'
|
||||
|
||||
import RiskAge from './parser/risk/age.js'
|
||||
import RiskHealthConditions from './parser/risk/health-conditions.js'
|
||||
|
||||
async function main() {
|
||||
const sources = await fg(['./data/raw/*.zip'])
|
||||
@@ -27,6 +28,7 @@ async function main() {
|
||||
await OverallDeaths(zips, counties)
|
||||
|
||||
await RiskAge(zips)
|
||||
await RiskHealthConditions(zips)
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
46
data/parser/risk/health-conditions.js
Normal file
46
data/parser/risk/health-conditions.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import mkdirp from 'mkdirp'
|
||||
import path from 'path'
|
||||
import fsp from 'fs/promises'
|
||||
import Papa from 'papaparse'
|
||||
import { getCounty } from '../../util.js'
|
||||
|
||||
async function processSingleZip ({ date, zip }) {
|
||||
const output = {
|
||||
directory: `./public/data/risk/health-conditions/`,
|
||||
file: `health-conditions.json`
|
||||
}
|
||||
|
||||
try {
|
||||
await fsp.rm(output.directory, { recursive: true })
|
||||
} catch (e) {}
|
||||
|
||||
const csv = await zip.entryData('comorbidities_sum.csv').then(res => res.toString())
|
||||
|
||||
const rows = Papa.parse(csv, {
|
||||
header: true
|
||||
}).data
|
||||
|
||||
const results = rows.map(row => {
|
||||
return {
|
||||
health_condition: row.comorbidity,
|
||||
sex: row.sex,
|
||||
cases: +row.cases,
|
||||
deaths: +row.deaths
|
||||
}
|
||||
}).filter(row => !!row.health_condition)
|
||||
|
||||
const data = {
|
||||
segment: { },
|
||||
headers: Object.keys(results[0]),
|
||||
rows: results.map(row => Object.values(row))
|
||||
}
|
||||
|
||||
await mkdirp(output.directory)
|
||||
await fsp.writeFile(path.join(output.directory, output.file), JSON.stringify(data))
|
||||
}
|
||||
|
||||
function process (zips) {
|
||||
return processSingleZip(zips.at(-1))
|
||||
}
|
||||
|
||||
export default process
|
||||
@@ -0,0 +1 @@
|
||||
{"segment":{},"headers":["health_condition","sex","cases","deaths"],"rows":[["Any Chronic Condition","Female",160346,6087],["Any Chronic Condition","Male",125662,6987],["Any Chronic Condition","Total",286274,13077],["Any Chronic Condition","Unknown",266,3],["Any Disability","Female",11801,1587],["Any Disability","Male",9456,1434],["Any Disability","Total",21276,3021],["Any Disability","Unknown",19,0],["Cardiovascular Disease","Female",29854,3071],["Cardiovascular Disease","Male",27385,3746],["Cardiovascular Disease","Total",57273,6819],["Cardiovascular Disease","Unknown",34,2],["Chronic Liver Disease","Female",1819,163],["Chronic Liver Disease","Male",1577,257],["Chronic Liver Disease","Total",3397,420],["Chronic Liver Disease","Unknown",1,0],["Chronic Lung Disease","Female",43275,1738],["Chronic Lung Disease","Male",27761,1763],["Chronic Lung Disease","Total",71106,3502],["Chronic Lung Disease","Unknown",70,1],["Chronic Renal Disease","Female",6815,1345],["Chronic Renal Disease","Male",6600,1669],["Chronic Renal Disease","Total",13421,3016],["Chronic Renal Disease","Unknown",6,2],["Currently Pregnant","Female",8779,22],["Currently Pregnant","Male",0,0],["Currently Pregnant","Total",8783,22],["Currently Pregnant","Unknown",4,0],["Diabetes Mellitus","Female",36341,2519],["Diabetes Mellitus","Male",30965,3055],["Diabetes Mellitus","Total",67365,5576],["Diabetes Mellitus","Unknown",59,2],["Hypertension/High blood pressure","Female",32438,1660],["Hypertension/High blood pressure","Male",25379,1829],["Hypertension/High blood pressure","Total",57879,3489],["Hypertension/High blood pressure","Unknown",62,0],["ICU","Female",6345,2682],["ICU","Male",7999,3559],["ICU","Total",14367,6244],["ICU","Unknown",23,3],["Immunocompromised Condition","Female",9333,550],["Immunocompromised Condition","Male",5405,612],["Immunocompromised Condition","Total",14746,1162],["Immunocompromised Condition","Unknown",8,0],["Missing/Unknown status on all conditions","Female",363168,1173],["Missing/Unknown status on all conditions","Male",329985,1327],["Missing/Unknown status on all conditions","Total",701056,2502],["Missing/Unknown status on all conditions","Unknown",7903,2],["None of the above conditions","Female",386415,10347],["None of the above conditions","Male",305984,11906],["None of the above conditions","Total",693561,22253],["None of the above conditions","Unknown",1162,0],["Obesity (BMI>40)","Female",11896,421],["Obesity (BMI>40)","Male",6482,387],["Obesity (BMI>40)","Total",18389,808],["Obesity (BMI>40)","Unknown",11,0],["Other Chronic Diseases","Female",38442,2488],["Other Chronic Diseases","Male",25104,2527],["Other Chronic Diseases","Total",63599,5015],["Other Chronic Diseases","Unknown",53,0],["Smoker","Female",38238,967],["Smoker","Male",45056,1801],["Smoker","Total",83347,2768],["Smoker","Unknown",53,0],["Total with completed information","Female",400790,11146],["Total with completed information","Male",316997,12774],["Total with completed information","Total",718978,23923],["Total with completed information","Unknown",1191,3]]}
|
||||
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<Card v-for="chart of charts" :key="chart.health_condition">
|
||||
<h2 class="mb-2 text-xl text-indigo-900 flex justify-between items-center">
|
||||
{{chart.health_condition}}
|
||||
</h2>
|
||||
<JSCharting :options="chart.options"></JSCharting>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { col } from '@/components/charts/util'
|
||||
import store from '@/components/charts/risk/health-conditions/store.js'
|
||||
|
||||
const data = store.data
|
||||
|
||||
const rows = computed(() => {
|
||||
if (!data.value) return []
|
||||
return data.value.rows.filter(r => {
|
||||
return !['Missing/Unknown status on all conditions','Total with completed information'].includes(col(data, r, 'health_condition'))
|
||||
})
|
||||
})
|
||||
|
||||
const charts = computed(() => {
|
||||
if (!rows.value) return {}
|
||||
|
||||
const dataSet = rows.value.reduce((obj, r) => {
|
||||
const sex = col(data, r, 'sex')
|
||||
if (sex !== 'Total') return obj
|
||||
const health_condition = col(data, r, 'health_condition')
|
||||
|
||||
const cases = col(data, r, 'cases')
|
||||
const deaths = col(data, r, 'deaths')
|
||||
|
||||
console.log(cases, deaths)
|
||||
|
||||
if (!obj[health_condition]) obj[health_condition] = {
|
||||
health_condition,
|
||||
points: [
|
||||
{ name: 'Cases', y: cases },
|
||||
{ name: 'Deaths', y: deaths }
|
||||
]
|
||||
}
|
||||
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
return Object.values(dataSet).map(({ health_condition, points }) => {
|
||||
return {
|
||||
health_condition,
|
||||
options: {
|
||||
type: 'column',
|
||||
legend_visible: true,
|
||||
debug: true,
|
||||
// yAxis: { scale: { type: 'logarithmic', logBase: 10 } },
|
||||
legend_position: 'bottom',
|
||||
defaultSeries_type: 'column',
|
||||
series: [{
|
||||
palette: 'default',
|
||||
points: points
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
15
src/components/charts/risk/health-conditions/store.js
Normal file
15
src/components/charts/risk/health-conditions/store.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
|
||||
const store = {
|
||||
data: ref(null)
|
||||
}
|
||||
|
||||
async function refreshData() {
|
||||
store.data.value = await fetch(`/data/risk/health-conditions/health-conditions.json`).then(res => res.json())
|
||||
}
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
|
||||
export default store
|
||||
@@ -64,20 +64,24 @@
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{path: '/risk/gender'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-mdi-gender-male-female class="mr-2"></icon-mdi-gender-male-female> by gender?
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{path: '/risk/ethnicity'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-mdi-web class="mr-2"></icon-mdi-web> by ethnicity?
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{path: '/risk/health-condition'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<router-link :to="{path: '/risk/health-conditions'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-healthicons-clinical-f-outline class="mr-2"></icon-healthicons-clinical-f-outline> by health condition?
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="flex items-center justify-between">
|
||||
<!-- <router-link :to="{path: '/risk/gender'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800"> -->
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-mdi-gender-male-female class="mr-2"></icon-mdi-gender-male-female> by gender?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Soon</span>
|
||||
</li>
|
||||
<li class="flex items-center justify-between">
|
||||
<!-- <router-link :to="{path: '/risk/ethnicity'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800"> -->
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-mdi-web class="mr-2"></icon-mdi-web> by ethnicity?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Soon</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
17
src/pages/risk/health-conditions.mdx
Normal file
17
src/pages/risk/health-conditions.mdx
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Who is most at risk by health condition?
|
||||
---
|
||||
|
||||
<Card class="col-span-1" prose={true}>
|
||||
# Who is most at risk by condition?
|
||||
|
||||
## What is this report useful for?
|
||||
|
||||
This report provides charts indicating the number of cases and deaths for a number of tracked medical conditions.
|
||||
|
||||
You may find it useful for assessing the relative risk of COVID to yourself or others.
|
||||
</Card>
|
||||
|
||||
<div class="grid gap-2 lg:gap-4 grid-cols-1 xl:grid-cols-4">
|
||||
<TrendRiskHealthConditions client:load/>
|
||||
</div>
|
||||
Reference in New Issue
Block a user