This perspective-workspace
uses perspective-python
to host the dataset in a remote server. When you load the page, the datset is serialized to Apache Arrow and streamed to the browser.
-
-
Save ix4/e97bd109b6d527fd9b5da9c3ba376b36 to your computer and use it in GitHub Desktop.
Perspective Workspace for COVID-19 U.S. Data
This file contains hidden or 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
license: apache-2.0 | |
height: 800 |
This file contains hidden or 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>COVID-19 Perspective Workspace</title> | |
<meta name="viewport" | |
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective-workspace/umd/perspective-workspace.js"> | |
</script> | |
<script | |
src="https://perspective-covid.herokuapp.com/static/perspective-viewer-datagrid/umd/perspective-viewer-datagrid.js"> | |
</script> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective-viewer-d3fc/umd/perspective-viewer-d3fc.js"> | |
</script> | |
<script src="https://perspective-covid.herokuapp.com/static/perspective/umd/perspective.js"></script> | |
<link rel="stylesheet" | |
href="https://perspective-covid.herokuapp.com/static/perspective-workspace/umd/material.css" /> | |
<style> | |
body { | |
display: flex; | |
flex-direction: column; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
} | |
</style> | |
</head> | |
<body> | |
<perspective-workspace id="workspace"></perspective-workspace> | |
<script> | |
const worker = perspective.shared_worker(); | |
const state_data = async websocket => { | |
// Get a proxy for a view named "state_data_source", registered on | |
// the server with a reciprocal call to `host_view()`. | |
// No data is transferred, `view` is a virtual handle for data on | |
// the server. | |
const view = websocket.open_view("state_data_source"); | |
// Create a `table` from this, owned by the local WebWorker. | |
// Data is transferred from `view` to the local WebWorker, both | |
// the current state and all future updates, as Arrows. | |
return worker.table(view); | |
}; | |
const county_data = async websocket => { | |
// Get a proxy for a view named "state_data_source", registered on | |
// the server with a reciprocal call to `host_view()`. | |
// No data is transferred, `view` is a virtual handle for data on | |
// the server. | |
const view = websocket.open_view("county_data_source"); | |
// Create a `table` from this, owned by the local WebWorker. | |
// Data is transferred from `view` to the local WebWorker, both | |
// the current state and all future updates, as Arrows. | |
return worker.table(view); | |
}; | |
window.addEventListener("load", async () => { | |
const websocket = perspective.websocket( | |
"wss://perspective-covid.herokuapp.com/ws" | |
); | |
window.workspace.addTable("state", state_data(websocket)); | |
window.workspace.addTable("county", county_data(websocket)); | |
const line_config = window.getPlugin("d3_y_line"); | |
line_config.max_cells = 200000; | |
line_config.max_columns = 7500; | |
await window.workspace.restore({ | |
sizes: [0.23643658663883088, 0.7635634133611691], | |
detail: { | |
main: { | |
type: "split-area", | |
orientation: "horizontal", | |
children: [ | |
{ | |
type: "tab-area", | |
widgets: [ | |
"CountyCasesWidget" | |
], | |
currentIndex: 0 | |
}, | |
{ | |
type: "split-area", | |
orientation: "vertical", | |
children: [{ | |
type: "tab-area", | |
widgets: ["CountyScatterWidget"], | |
currentIndex: 0 | |
}, | |
{ | |
type: "tab-area", | |
widgets: ["CountyPopulationWidget"], | |
currentIndex: 0 | |
} | |
], | |
sizes: [0.5, 0.5] | |
}, | |
], | |
sizes: [0.5, 0.5] | |
} | |
}, | |
master: { | |
widgets: ["MasterStateWidget", "MasterDateWidget"] | |
}, | |
mode: "globalFilters", | |
viewers: { | |
MasterStateWidget: { | |
plugin: "datagrid", | |
name: "Cases & Deaths by State", | |
table: "state", | |
"computed-columns": [ | |
"'New Deaths' % 'New Cases' as 'Fatality Rate (%)'" | |
], | |
columns: [ | |
"Fatality Rate (%)", | |
"New Cases", | |
"New Deaths" | |
], | |
"row-pivots": ["State Name"], | |
aggregates: { | |
"Cumulative Cases": "high", | |
"Cumulative Deaths": "high", | |
"Fatality Rate (%)": "avg", | |
"Date": "dominant" | |
}, | |
sort: [ | |
["Cumulative Cases", "desc"] | |
] | |
}, | |
MasterDateWidget: { | |
plugin: "datagrid", | |
name: "Cases & Deaths by Date", | |
table: "state", | |
"computed-columns": [ | |
"'New Deaths' % 'New Cases' as 'Fatality Rate (%)'" | |
], | |
columns: [ | |
"Fatality Rate (%)", | |
"New Cases", | |
"New Deaths" | |
], | |
sort: [ | |
["Date", "desc"] | |
], | |
"row-pivots": ["Date"], | |
aggregates: { | |
"Cumulative Cases": "high", | |
"Cumulative Deaths": "high", | |
"Fatality Rate (%)": "avg", | |
Date: "dominant" | |
} | |
}, | |
CountyCasesWidget: { | |
plugin: "d3_y_line", | |
name: "Cases since March 1st", | |
table: "county", | |
columns: ["Cumulative Cases"], | |
"row-pivots": ["Date"], | |
"column-pivots": ["Location"], | |
aggregates: { | |
"Date": "dominant", | |
"Cumulative Cases": "high", | |
"Cumulative Deaths": "high", | |
"Population (2018 Estimate)": "high", | |
"Unemployment Rate % (2018 Estimate)": "high", | |
"Unemployed (2018 Estimate)": "high", | |
"Employed (2018 Estimate)": "high", | |
"Civilian Labor Force (2018 Estimate)": "high", | |
"Median Household Income (2018 Estimate)": "high", | |
}, | |
"computed-columns": [ | |
'concat_comma("County", "State") as "Location"' | |
], | |
plugin_config: { | |
legend: { | |
left: "80px", | |
top: "15px" | |
} | |
} | |
}, | |
CountyScatterWidget: { | |
plugin: "d3_xy_scatter", | |
name: "Cases & Deaths Scatter Plot (by county)", | |
table: "county", | |
columns: ["New Cases", "New Deaths"], | |
"row-pivots": ["Location"], | |
aggregates: { | |
"Date": "dominant", | |
"Cumulative Cases": "high", | |
"Cumulative Deaths": "high", | |
"Population (2018 Estimate)": "high", | |
"Unemployment Rate % (2018 Estimate)": "high", | |
"Unemployed (2018 Estimate)": "high", | |
"Employed (2018 Estimate)": "high", | |
"Civilian Labor Force (2018 Estimate)": "high", | |
"Median Household Income (2018 Estimate)": "high", | |
}, | |
"computed-columns": [ | |
'concat_comma("County", "State") as "Location"' | |
] | |
}, | |
CountyPopulationWidget: { | |
name: "Cases/Deaths with county-level population, income, unemployment data", | |
table: "county", | |
plugin: "datagrid", | |
columns: [ | |
"Cases % Population", | |
"New Cases", | |
"New Deaths", | |
"Population (2018 Estimate)", | |
"Unemployed (2018 Estimate)", | |
"Employed (2018 Estimate)", | |
"Civilian Labor Force (2018 Estimate)", | |
"Median Household Income (2018 Estimate)", | |
], | |
sort: [["Population (2018 Estimate)", "desc"]], | |
aggregates: { | |
"Cases % Population": "avg", | |
"Date": "dominant", | |
"Cumulative Cases": "high", | |
"Cumulative Deaths": "high", | |
"Population (2018 Estimate)": "high", | |
"Unemployment Rate % (2018 Estimate)": "high", | |
"Unemployed (2018 Estimate)": "high", | |
"Employed (2018 Estimate)": "high", | |
"Civilian Labor Force (2018 Estimate)": "high", | |
"Median Household Income (2018 Estimate)": "high", | |
}, | |
"row-pivots": ["Location"], | |
"computed-columns": [ | |
'concat_comma("County", "State") as "Location"', | |
"'New Cases' % 'Population (2018 Estimate)' as 'Cases % Population'" | |
] | |
}, | |
} | |
}); | |
// Custom formatting for the datagrid - display percentages with a `%` | |
for (const viewer of document | |
.getElementById("workspace") | |
.querySelectorAll("perspective-viewer")) { | |
viewer.addEventListener( | |
"perspective-datagrid-after-update", | |
event => { | |
const datagrid = event.detail; | |
for (const td of datagrid.get_tds()) { | |
const metadata = datagrid.get_meta(td); | |
if ( | |
metadata.column.includes("%") && | |
typeof metadata.value === "number" | |
) { | |
const pct = metadata.value | |
.toFixed(4) | |
.toString(); | |
td.textContent = pct + "%"; | |
} else if (metadata.column === "Median Household Income (2018 Estimate)") { | |
td.textContent = "$" + metadata.value; | |
} else { | |
td.style.display = "table-cell"; | |
} | |
} | |
} | |
); | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment