Module:Medical cases data
| This module is rated as alpha. It is ready for limited use and third-party feedback. It may be used on a small number of pages, but should be monitored closely. Suggestions for new features or adjustments to input and output are welcome. |
This module inserts charts and maps of medical cases related to a pandemic, broken down by subregions.
caseTable
Inserts a table of cases and deaths by region.
Usage: {{#invoke:Medical cases data|caseTable|config=Configuration}}
{{#invoke:Medical cases data|caseTable
|config=San Francisco Bay Area
}}
| Counties | Cases[a] | Recov.[b] | Deaths | Pop. (2019) | C/1M | Ref. |
|---|---|---|---|---|---|---|
| 9 | 1,948,760 | 11,354 | 7,739,378 | 251,798 | ||
| Santa Clara | 539,276 | ? | 3,226 | 1,927,852 | 279,729 | d c[1] |
| Alameda[c] | 400,532 | ? | 2,573 | 1,671,329 | 239,649 | d c[2] |
| Contra Costa | 302,824 | 300,666 | 1,601 | 1,153,526 | 262,520 | d c[3] |
| San Francisco | 203,788 | ? | 1,419 | 881,549 | 231,170 | d c[4] |
| San Mateo | 184,001 | ? | 946 | 766,573 | 240,031 | d c[5] |
| Sonoma | 119,749 | 118,903 | 667 | 494,336 | 242,242 | d c[6] |
| Solano | 118,904 | 118,073 | 441 | 447,643 | 265,622 | d c[7] |
| Marin | 44,650 | 7,030 | 274 | 258,826 | 172,510 | d c[8] |
| Napa | 35,036 | 27,672 | 207 | 137,744 | 254,356 | d c[9] |
| ||||||
map
Inserts an interactive map of cases and deaths by region.
Usage: {{#invoke:Medical cases data|map|config=Configuration|frameWidth=Frame width in pixels|frameHeight=Frame height in pixels|caption=Caption as wikitext}}
{{#invoke:Medical cases data|map
|config=San Francisco Bay Area
|frameHeight=300
}}
Configuration
Run this Wikidata Query Service query to obtain a list of localized outbreaks to add to the regions property in the table.
return {
caption = "Cases by county", -- Table or map caption as wikitext
outbreakItem = "Q94050008", -- QID of the Wikidata item representing the
regionTerm = "Counties", -- Term for each region, used as the first column's header
regionNamePattern = "(.+) County", -- Naming pattern for regions, applied to each region's item's label to display a short name in first column; see [[mw:Extension:Scribunto/Lua reference manual#Patterns]]
populationDate = "2020-01-01", -- Date of the population figures used to calculate per-capita infection rates
regions = {
-- Add a table for each region's outbreak
{
-- QID of the outbreak
entity = "Q94259368",
-- If there is tabular data for the outbreak, specify any column names that differ from the defaults
columns = {cases = "AC_CumulCases", deaths = "AC_CumulDeaths"},
-- Optional footnote for the region as wikitext
note = "Including cases in the City of Berkeley, which are reported by the Berkeley Public Health Division.",
},
},
columnNotes = {
cases = "Cumulative cases reported by each county's health department.", -- (Optional) Footnote for the "Cases" column as wikitext
recoveries = "Counties differ in what they consider to be a recovery.", -- (Optional) Footnote for the "Recoveries" column as wikitext
deaths = "Includes suspected cases.", -- (Optional) Footnote for the "Deaths" column as wikitext
}
}
Available configurations
- ^ “Respiratory virus data”, “COVID cases and deaths dashboard”, “COVID-19 hospitalizations by date”, “COVID-19 Hospitalizations Dashboard”, “Count of deaths with COVID-19 by date”, “Deaths with COVID-19 by age group”, Santa Clara County Public Health. April 9, 2026.
- ^ Alameda County Data Sharing Initiative, Alameda County Public Health Department. December 27, 2025.
- ^ Contra Costa Health Services. May 22, 2023.
- ^ “ARCHIVED: COVID-19 Cases by Geography Over Time”, “COVID-19 Deaths Over Time”, “COVID-19 Hospitalizations”, DataSF, San Francisco Department of Public Health. March 31, 2026.
- ^ San Mateo County Health. April 27, 2023.
- ^ Case and Testing Data, Hospitalizations and Deaths, County of Sonoma. April 26, 2024.
- ^ Solano County Public Health. March 2, 2023.
- ^ “COVID-19 Case Disposition”, “COVID-19 Cumulative Demographics”, “Total Cases and Recovered by Date Reported among Marin County Community Residents”, “Total Hospitalizations and Deaths by Event Date among Marin County Community Residents”, Marin Health & Human Services. February 14, 2023.
- ^ “COVID-19 in Napa County”, “Landing Page”, “Situation Update Archive”, Napa County Health & Human Services Agency. May 14, 2023.
-- Usage: =p._caseTable({config="San Francisco Bay Area"})
local p = {}
local lang = mw.getContentLanguage()
local tabularData = require("Module:Tabular data")
local wd = require("Module:wd")
local mapFrame = require("Module:Mapframe")
local propertyIDsByDisposition = {
-- tests = "P8011",
cases = "P1603",
-- hospitalizations = "P8049",
recoveries = "P8010",
deaths = "P1120",
}
local function round(x)
return (math.modf(x + (x < 0 and -0.5 or 0.5)))
end
function p.pointInTime(statement)
local qualifiers = statement.qualifiers and statement.qualifiers.P585
local time = qualifiers and qualifiers[1].datavalue.value.time
return time and tonumber(lang:formatDate("U", time))
end
-- =tonumber(p.mostRecentStatement("Q83873577", "P1120").mainsnak.datavalue.value.amount)
function p.mostRecentStatement(entityID, propertyID, startDate, endDate)
local startTime = startDate and tonumber(lang:formatDate("U", startDate)) or -math.huge
local endTime = endDate and tonumber(lang:formatDate("U", endDate)) or math.huge
local statements = mw.wikibase.getBestStatements(entityID, propertyID)
local latestTime = -math.huge
local latestStatement
for i, statement in ipairs(statements) do
local time = p.pointInTime(statement)
if time and time > startTime and time < endTime and time > latestTime then
latestTime = time
latestStatement = statement
end
end
return latestStatement
end
function p.statementReference(statement)
local reference = statement.references and statement.references[1]
local referenceSnak = reference and reference.snaks.P248 and reference.snaks.P248[1]
local declarationQID = referenceSnak and referenceSnak.datavalue.value.id
if not declarationQID then
return nil
end
local name = mw.wikibase.formatValue(referenceSnak)
local url = mw.wikibase.getBestStatements(declarationQID, "P856")[1].mainsnak.datavalue.value
return {
name = declarationQID,
wikitext = url and mw.ustring.format("[%s %s]", url, name) or name,
}
end
function p._regionData(regionConfigs, populationDate, ignoredSources)
local regions = {}
for i, regionConfig in ipairs(regionConfigs) do
local outbreakEntity = regionConfig.entity
local locationEntity = mw.wikibase.getBestStatements(outbreakEntity, "P276")[1].mainsnak.datavalue.value.id
local dataTableStatement = mw.wikibase.getBestStatements(outbreakEntity, "P8204")[1]
local dataTableName
local dataTable
if dataTableStatement then
local qualifiers = dataTableStatement and dataTableStatement.qualifiers
local source = qualifiers and qualifiers.P1433 and qualifiers.P1433[1].datavalue.value.id
local ignored = false
for i, ignoredSource in ipairs(ignoredSources or {}) do
if source == ignoredSource then
ignored = true
break
end
end
if not ignored then
dataTableName = dataTableStatement.mainsnak.datavalue.value
dataTable = mw.ext.data.get((dataTableName:gsub("^Data:", "")))
end
end
local region = {
outbreakEntity = outbreakEntity,
locationEntity = locationEntity,
name = mw.wikibase.getLabel(locationEntity),
link = mw.wikibase.getSitelink(locationEntity),
population = tonumber(wd._property({
"raw",
locationEntity,
"P1082",
P585 = populationDate,
})),
dataTableName = dataTableName,
note = regionConfig.note,
sources = {},
}
local columns = regionConfig.columns
local latestTableDate = dataTable and tabularData._cell({
data = dataTable,
output_row = -1,
output_column = columns and (columns.date or columns.P585_date) or "date",
})
local latestTableTime = latestTableDate and tonumber(lang:formatDate("U", latestTableDate))
local usesDataTable = false
local casesStatement = p.mostRecentStatement(outbreakEntity, propertyIDsByDisposition.cases)
local casesTime = casesStatement and p.pointInTime(casesStatement)
if casesTime and (not latestTableTime or casesTime > latestTableTime) then
region.cases = tonumber(casesStatement.mainsnak.datavalue.value.amount)
local reference = p.statementReference(casesStatement)
if reference then
region.sources[reference.name] = reference.wikitext
end
elseif latestTableTime then
region.cases = dataTable and (tabularData._cell({
data = dataTable,
output_row = -1,
output_column = columns and columns.cases or "totalConfirmedCases",
}) or tabularData._lookup({
data = dataTable,
search_pattern = "%d",
search_column = columns and columns.cases or "totalConfirmedCases",
occurrence = -1,
output_column = columns and columns.cases or "totalConfirmedCases",
})) + (columns and columns.cases2 and tabularData._cell({
data = dataTable,
output_row = -1,
output_column = columns.cases2,
}) or 0)
usesDataTable = true
end
region.arrivalDate = dataTable and tabularData._lookup({
data = dataTable,
search_pattern = "[1-9]",
search_column = columns and columns.cases or "totalConfirmedCases",
occurrence = 1,
output_column = columns and (columns.date or columns.P585_date) or "date",
})
local deathsStatement = p.mostRecentStatement(outbreakEntity, propertyIDsByDisposition.deaths)
local deathsTime = deathsStatement and p.pointInTime(deathsStatement)
if deathsTime and (not latestTableTime or deathsTime > latestTableTime) then
region.deaths = tonumber(deathsStatement.mainsnak.datavalue.value.amount)
local reference = p.statementReference(deathsStatement)
if reference then
region.sources[reference.name] = reference.wikitext
end
elseif latestTableTime then
region.deaths = dataTable and (tabularData._cell({
data = dataTable,
output_row = -1,
output_column = columns and columns.deaths or "deaths",
}) or tabularData._lookup({
data = dataTable,
search_pattern = "%d",
search_column = columns and columns.deaths or "deaths",
occurrence = -1,
output_column = columns and columns.deaths or "deaths",
}))
usesDataTable = true
end
local recoveriesStatement = p.mostRecentStatement(outbreakEntity, propertyIDsByDisposition.recoveries)
local recoveriesTime = recoveriesStatement and p.pointInTime(recoveriesStatement)
if recoveriesTime and (not latestTableTime or recoveriesTime > latestTableTime) then
region.recoveries = tonumber(recoveriesStatement.mainsnak.datavalue.value.amount)
local reference = p.statementReference(recoveriesStatement)
if reference then
region.sources[reference.name] = reference.wikitext
end
elseif latestTableTime then
region.recoveries = columns and columns.recoveries and dataTable and (tabularData._cell({
data = dataTable,
output_row = -1,
output_column = columns.recoveries,
}) or tabularData._lookup({
data = dataTable,
search_pattern = "%d",
search_column = columns.recoveries,
occurrence = -1,
output_column = columns.recoveries,
}))
usesDataTable = true
end
local viewLinks = {
mw.ustring.format("[[d:%s|d]]", region.outbreakEntity),
}
if dataTableName then
table.insert(viewLinks, mw.ustring.format("[[c:%s|c]]", dataTableName))
end
region.viewLink = table.concat(viewLinks, " ")
if usesDataTable then
local formattedDate = latestTableTime
local reference = mw.ustring.format("%s. %s.", dataTable.sources:gsub("<br */?>.*", ""), lang:formatDate("F j, Y", latestTableDate))
region.sources[dataTableName] = reference
end
table.insert(regions, region)
end
return regions
end
local function addNumericCell(row, contents)
if contents then
row
:tag("td")
:attr("align", "right")
:attr("data-sort-value", contents)
:wikitext(lang:formatNum(contents))
else
row
:tag("td")
:addClass("unknown")
:addClass("table-unknown")
:attr("align", "center")
:css({
background = "#ececec",
color = "#2c2c2c",
["font-size"] = "smaller",
["vertical-align"] = "middle",
})
:attr("data-sort-value", "0")
:wikitext("?")
end
return row
end
-- Usage: =p._caseTable({config="San Francisco Bay Area"})
function p._caseTable(args)
local frame = mw.getCurrentFrame()
local config = args.config and mw.loadData("Module:Medical cases data/" .. args.config)
local populationDate = config and config.populationDate or args.populationDate
local regions = p._regionData(
config and config.regions,
populationDate,
config and config.ignoredSources)
table.sort(regions, function (left, right)
local leftCases = left.cases or 0
local rightCases = right.cases or 0
return leftCases == rightCases and left.name < right.name or leftCases > rightCases
end)
local totals = {
regions = #regions,
cases = 0,
deaths = 0,
recoveries = 0,
population = 0,
}
for i, region in ipairs(regions) do
totals.cases = totals.cases + (region.cases or 0)
totals.deaths = totals.deaths + (region.deaths or 0)
totals.recoveries = totals.recoveries and region.recoveries and (totals.recoveries + region.recoveries)
totals.population = totals.population + (region.population or 0)
end
local htmlTable = mw.html.create("table")
:addClass("wikitable")
:addClass("sortable")
:addClass("plainrowheaders")
:attr("align", "right")
:css({
["font-size"] = "85%",
})
htmlTable
:tag("caption")
:wikitext(config and config.caption or args.caption)
local headerRow = htmlTable
:tag("tr")
local totalRow = htmlTable
:tag("tr")
local columnNotes = config and config.columnNotes
headerRow
:tag("th")
:attr("scope", "col")
:attr("data-sort-type", "text")
:wikitext(config and config.regionTerm or args.regionTerm or "Regions")
:wikitext(columnNotes and columnNotes.regions and frame:expandTemplate {
title = "efn",
args = {
columnNotes.regions
}
})
totalRow
:tag("th")
:attr("align", "right")
:wikitext(lang:formatNum(totals.regions))
headerRow
:tag("th")
:attr("scope", "col")
:attr("data-sort-type", "number")
:wikitext("Cases")
:wikitext(columnNotes and columnNotes.cases and frame:expandTemplate {
title = "efn",
args = {
columnNotes.cases
}
})
totalRow
:tag("th")
:attr("align", "right")
:attr("data-sort-type", "number")
:wikitext(lang:formatNum(totals.cases))
local recoveriesHeader = headerRow
:tag("th")
:attr("scope", "col")
:attr("data-sort-type", "number")
recoveriesHeader
:tag("abbr")
:attr("title", "Recoveries")
:wikitext("Recov.")
recoveriesHeader
:wikitext(columnNotes and columnNotes.recoveries and frame:expandTemplate {
title = "efn",
args = {
columnNotes.recoveries
}
})
totalRow
:tag("th")
:attr("align", "right")
:wikitext(totals.recoveries and lang:formatNum(totals.recoveries))
headerRow
:tag("th")
:attr("scope", "col")
:attr("data-sort-type", "number")
:wikitext("Deaths")
:wikitext(columnNotes and columnNotes.deaths and frame:expandTemplate {
title = "efn",
args = {
columnNotes.deaths
}
})
totalRow
:tag("th")
:attr("align", "right")
:attr("data-sort-type", "number")
:wikitext(lang:formatNum(totals.deaths))
local populationHeader = headerRow
:tag("th")
:attr("scope", "col")
:attr("data-sort-type", "number")
populationHeader
:tag("abbr")
:attr("title", "Population")
:wikitext("Pop.")
if populationDate then
populationHeader
:wikitext(mw.ustring.format(" (%d)", lang:formatDate("Y", populationDate)))
end
populationHeader
:wikitext(columnNotes and columnNotes.population and frame:expandTemplate {
title = "efn",
args = {
columnNotes.population
}
})
totalRow
:tag("th")
:attr("align", "right")
:attr("data-sort-type", "number")
:wikitext(lang:formatNum(totals.population))
headerRow
:tag("th")
:attr("scope", "col")
:attr("data-sort-type", "number")
:tag("abbr")
:attr("title", "Cases per 1 million inhabitants")
:wikitext("C/1M")
:wikitext(columnNotes and columnNotes.casesPerMillion and frame:expandTemplate {
title = "efn",
args = {
columnNotes.casesPerMillion
}
})
totalRow
:tag("th")
:attr("align", "right")
:attr("data-sort-type", "number")
:wikitext(lang:formatNum(round(totals.cases / totals.population * 1e6)))
headerRow
:tag("th")
:attr("scope", "col")
:attr("rowspan", 2)
:addClass("unsortable")
:tag("abbr")
:attr("title", "Reference")
:wikitext("Ref.")
local regionNamePattern = config and config.regionNamePattern or args.regionNamePattern
for i, region in ipairs(regions) do
local row = htmlTable:tag("tr")
local name = region.name
if regionNamePattern then
name = mw.ustring.match(region.name, regionNamePattern) or name
end
row
:tag("th")
:attr("scope", "row")
:wikitext(mw.ustring.format("[[%s|%s]]", region.link, name))
:wikitext(region.note and frame:expandTemplate {
title = "efn",
args = {
region.note,
}
})
addNumericCell(row, region.cases)
addNumericCell(row, region.recoveries)
addNumericCell(row, region.deaths)
addNumericCell(row, region.population)
addNumericCell(row, region.cases and region.population and round(region.cases / region.population * 1e6))
local refCell = row
:tag("td")
:attr("align", "center")
:wikitext(region.viewLink)
for name, wikitext in pairs(region.sources) do
refCell:wikitext(frame:callParserFunction {
name = "#tag:ref",
args = {
name = name,
wikitext,
},
})
end
end
local footerRow = htmlTable
:tag("tr")
:addClass("sortbottom")
footerRow
:tag("td")
:attr("colspan", 7)
:attr("align", "left")
:css({
width = 0,
})
:wikitext(frame:expandTemplate {
title = "notelist",
})
return htmlTable
end
function p.caseTable(frame)
return p._caseTable(frame.args)
end
function p._statistics(args)
local frame = mw.getCurrentFrame()
local config = args.config and mw.loadData("Module:Medical cases data/" .. args.config)
local populationDate = config and config.populationDate or args.populationDate
local regions = p._regionData(
config and config.regions,
populationDate,
config and config.ignoredSources)
local stats = {
regions = #regions,
cases = 0,
deaths = 0,
recoveries = 0,
recoveriesRegions = 0,
population = 0,
}
for i, region in ipairs(regions) do
stats.cases = stats.cases + (region.cases or 0)
stats.deaths = stats.deaths + (region.deaths or 0)
if region.recoveries then
stats.recoveries = stats.recoveries + region.recoveries
stats.recoveriesRegions = stats.recoveriesRegions + 1
end
stats.population = stats.population + (region.population or 0)
if not stats.arrivalDate or region.arrivalDate < stats.arrivalDate then
stats.arrivalDate = region.arrivalDate
end
end
return stats
end
function p.statistics(frame)
return p._statistics(frame.args)[mw.text.trim(frame.args[1])]
end
local function fillColor(casesPerCapita)
-- [[c:Template:COVID-19 Prevalence in US by county]]
local percent = casesPerCapita * 100
if percent >= 10.00 then return "#510000" end
if percent >= 3.00 then return "#99000d" end
if percent >= 1.00 then return "#cb181d" end
if percent >= 0.30 then return "#fb6a4a" end
if percent >= 0.10 then return "#fc9272" end
if percent >= 0.03 then return "#fcbba1" end
if percent >= 0.00 then return "#fee5d9" end
return "#cccccc"
end
-- Usage: =p._map({config="San Francisco Bay Area"})
function p._map(args)
local frame = mw.getCurrentFrame()
local config = args.config and mw.loadData("Module:Medical cases data/" .. args.config)
local populationDate = config and config.populationDate or args.populationDate
local regions = p._regionData(
config and config.regions,
populationDate,
config and config.ignoredSources)
local params = {
frame = "yes",
["frame-width"] = args.frameWidth or (config and config.frameWidth),
["frame-height"] = args.frameHeight or (config and config.frameHeight),
text = args.caption or (config and config.caption),
}
for i, region in ipairs(regions) do
i = i == 1 and "" or i
params["type" .. i] = "shape"
params["id" .. i] = region.locationEntity
params["title" .. i] = region.name
params["stroke-color" .. i] = "#ffffff"
params["stroke-width" .. i] = 1
params["fill" .. i] = fillColor(region.cases / region.population)
local details = {
mw.ustring.format("%s cases (%s/1M)", lang:formatNum(region.cases),
lang:formatNum(round(region.cases / region.population * 1e6))),
mw.ustring.format("%s deaths", lang:formatNum(region.deaths)),
}
if region.recoveries then
table.insert(details, mw.ustring.format("%s recoveries", lang:formatNum(region.recoveries)))
end
params["description" .. i] = table.concat(details, "<br>")
end
return frame:preprocess(mapFrame._main(params))
end
function p.map(frame)
return p._map(frame.args)
end
return p
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.
