chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1 @@
|
||||
license: apache-2.0
|
||||
@@ -0,0 +1,7 @@
|
||||
Demo of [Perspective](https://github.com/perspective-dev/perspective), using SF
|
||||
eviciton data from 1997-present provided by
|
||||
[DataSF](https://data.sfgov.org/Housing-and-Buildings/Eviction-Notices/5cei-gny5).
|
||||
|
||||
This example has no server component, and connects directly to DataSF's public
|
||||
API from your browser. These 44,311 rows are ~2.5mb gzipped (at time of
|
||||
writing), but are cached in `LocalStorage` on subsequent page visits.
|
||||
@@ -0,0 +1,84 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
|
||||
<link rel="preload" href="/node_modules/@perspective-dev/viewer/dist/wasm/perspective-viewer.wasm" as="fetch" type="application/wasm" crossorigin="anonymous" />
|
||||
<link rel="preload" href="/node_modules/@perspective-dev/server/dist/wasm/perspective-server.wasm" as="fetch" type="application/wasm" crossorigin="anonymous" />
|
||||
<link rel="stylesheet" crossorigin="anonymous" href="/node_modules/@perspective-dev/viewer/dist/css/themes.css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/fflate@0.7.3/umd/index.min.js"></script>
|
||||
<script type="module">
|
||||
import "/node_modules/@perspective-dev/viewer/dist/cdn/perspective-viewer.js";
|
||||
import "/node_modules/@perspective-dev/viewer-datagrid/dist/cdn/perspective-viewer-datagrid.js";
|
||||
import "/node_modules/@perspective-dev/viewer-charts/dist/cdn/perspective-viewer-charts.js";
|
||||
|
||||
import { worker } from "/node_modules/@perspective-dev/client/dist/cdn/perspective.js";
|
||||
|
||||
const WORKER = await worker();
|
||||
const URL = `https://data.sfgov.org/resource/5cei-gny5.csv?$limit=50000`;
|
||||
|
||||
async function get_evictions() {
|
||||
const arrow = localStorage.getItem(URL);
|
||||
if (arrow !== null) {
|
||||
console.log("Using cached data from localStorage");
|
||||
try {
|
||||
const buffer = fflate.strToU8(arrow, true);
|
||||
return await WORKER.table(fflate.decompressSync(buffer).buffer);
|
||||
} catch (e) {
|
||||
console.error("Can't load cached data", e);
|
||||
localStorage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Downloading data from data.sfgov.org");
|
||||
const resp = await fetch(
|
||||
URL,
|
||||
// "5cei-gny5.csv"
|
||||
// "evictions.all.arrow"
|
||||
);
|
||||
const csv = await resp.text();
|
||||
const table = await WORKER.table(csv);
|
||||
(async () => {
|
||||
console.log("Caching data");
|
||||
const view = await table.view();
|
||||
const arrow = await view.to_arrow();
|
||||
try {
|
||||
const x = fflate.compressSync(new Uint8Array(arrow));
|
||||
const zipped = fflate.strFromU8(x, true);
|
||||
localStorage.setItem(URL, zipped);
|
||||
} catch (e) {
|
||||
console.error("Can't cache data from data.sfgov.org", e);
|
||||
}
|
||||
})();
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
async function load() {
|
||||
const el = document.getElementsByTagName("perspective-viewer")[0];
|
||||
|
||||
const evictions = get_evictions();
|
||||
const layout_json = await fetch("layout.json");
|
||||
const layout = await layout_json.json();
|
||||
|
||||
el.load(await evictions);
|
||||
el.restore(layout);
|
||||
}
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
perspective-viewer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<perspective-viewer editable> </perspective-viewer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"plugin": "Map Scatter",
|
||||
"plugin_config": {},
|
||||
"settings": true,
|
||||
"theme": "Pro Dark",
|
||||
"group_by": ["bucket lon", "bucket lat"],
|
||||
"split_by": ["neighborhood"],
|
||||
"columns": ["lon", "lat", null, null, null],
|
||||
"filter": [["lon", "is not null", null]],
|
||||
"sort": [],
|
||||
"expressions": {
|
||||
"lon": "var x[2];\nindexof(\"shape\", ' .+?( )', x);\nvar y := substring(\"shape\", 7, x[1] - 7);\nfloat(y)",
|
||||
"lat": "var x[2];\nindexof(\"shape\", ' .+?( )', x);\nvar y := substring(\"shape\", x[0], length(\"shape\") - x[1]);\nfloat(y)",
|
||||
"bucket lon": "var x[2];\nindexof(\"shape\", ' .+?( )', x);\nvar y := substring(\"shape\", 7, x[1] - 7);\nbucket(float(y), 0.0025) + 0.00125",
|
||||
"bucket lat": "var x[2];\nindexof(\"shape\", ' .+?( )', x);\nvar y := substring(\"shape\", x[0], length(\"shape\") - x[1]);\nbucket(float(y), 0.0025) + 0.00125"
|
||||
},
|
||||
"aggregates": {
|
||||
"lon": "avg",
|
||||
"lat": "avg",
|
||||
"bucket lon": "avg",
|
||||
"bucket lat": "avg"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 366 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Reference in New Issue
Block a user