Public
Edited
Jul 28, 2023
7 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
wait_time_min = FileAttachment("wait_time_min@1.csv").csv({typed: true})
Insert cell
headway = FileAttachment("headway_by_date_hour@1.txt").csv({typed:true});
Insert cell
Insert cell
Insert cell
Insert cell
missing = Array(0)
Insert cell
{
let abc = Array.from(d3.flatRollup(data, v => {
return {
'date': v[0].date,
'sex': v[0].sex,
'ct': v.length,
}
}, d => d.date, d => d.sex), ([_, __, value]) => {_, value});
return abc
}
Insert cell
{
let abc = d3.flatRollup(data, v => v.length, d => d.date, d => d.sex);
return abc.map(([date, sex, count]) => ({date, sex, count}))
}
Insert cell
cohort = d3.groups(vehicleHealth, d => d.date)
Insert cell
cohort.map(d => {
let row = {};
row.date = d[0];
row.value = d[1];
return row;
})
// equivalent to the below
// cohort.map(d => ({date: d[0], value: d[1]}));
Insert cell
Insert cell
bins = d3.bin().thresholds([-10, -5, 0])
Insert cell
buckets = bins(wait_time_min.map(d => d.actual_wait_time_min));
Insert cell
binStats = buckets.map(d => {return {min: d3.min(d), max: d3.max(d), ct: d.length, pct: d.length / wait_time_min.length}})
Insert cell
Insert cell
// use long to wide algorithm; accomodates missing cell values
stack = {
const category1 = ['planned', 'unplanned'];
const category2 = ['boy', 'girl'];
const column = "takeover"
let group = d3.rollup(engage, v => d3.sum(v, d => d.count), d => d[column], d => d.type);
let stackInput = [];
for (let cat1 of category1) {
let row = {};
row[column] = cat1;
if (group.has(cat1)) {
const innermap = group.get(cat1);
category2.forEach(d => { row[d] = innermap.has(d) ? innermap.get(d) : 0 });
} else {
category2.forEach(d => { row[d] = 0 });
}
stackInput.push(row);
}
return d3.stack()
.keys(category2)(stackInput)
// .map(arr => arr.map(([y0, y1]) => [y0, y1, arr.index]))
}
Insert cell
Insert cell
combos = {
const famSorted = fam.sort();
let data = [];
for (let i=0; i<famSorted.length; i++) {
for (let j=i+1; j<famSorted.length; j++) {
data.push([famSorted[i], famSorted[j]])
}
}
return data
}
Insert cell
Insert cell
Insert cell
wide = Array.from(d3.rollup(data, v => d3.sum(v, d => d.count), d => d.date, d => d.sex), ([key,value]) => {
let row = {};
row['date'] = key;
const categories = new Set(data.map(d => d.sex));
categories.forEach(d => { row[d] = value.has(d) ? value.get(d) : 0 });
return row;
})
Insert cell
Insert cell
Insert cell
headoverall = {
let row = {};
row['key'] = 'overall';
for (let col of Object.keys(head[0]).slice(1)) {
row[col] = d3.sum(head, d => d[col])
}
return head.concat(row)
}
Insert cell
Insert cell
// option 1
widedata = Object.assign(wide, {columns: Object.keys(wide[0])});
Insert cell
// option 2
widedata2 = {
wide['columns'] = Object.keys(wide[0])
return wide
}
Insert cell
Insert cell
longdata = {
let data = [];
for (let d of widedata) {
for (let col of widedata.columns.slice(1)) {
if (d[col] > 0) {
let row = {};
row[widedata.columns[0]] = d[widedata.columns[0]];
row['gender'] = col;
row['count'] = d[col];
data.push(row);
}
}
};
return data;
}
Insert cell
Insert cell
emptyMap = {
let data = new Map;
for (let day of weekdayService) {
data.set(day, new Map);
for (let hr of hours) {
data.get(day).set(hr, 0);
}
}
return data
}
Insert cell
Insert cell
emptyArray = {
let data = [];
for (let day of weekdayService) {
for (let hr of hours) {
data.push({weekday: day, hour: hr, pickup: 0});
}
}
return data
}
Insert cell
Insert cell
alternation = {
let array1 = [1, 2, 3, 4, 5];
let array2 = ['a', 'b', 'c', 'd'];
return array1.map((d, i) => i < array2.length ? [d, array2[i]] : d).flat();
}
Insert cell
fleet = {
let fleetStatus = new Map;
d3.range(3).forEach(n => fleetStatus.set(n, 0));
let fleet = d3.rollup(vehicleHealth, v => v.length, d => d.health);
for (let [key, value] of fleet) {
fleetStatus.set(key, value);
}
return fleetStatus;
}
Insert cell
vehicleHealth = [
{may_id: "marty", health: 1, date: new Date(2022,1,15)},
{may_id: "mchale", health: 0, date: new Date(2022,1,14)},
{may_id: "mojo", health: 1, date: new Date(2022,1,14)},
{may_id: "molly", health: 1, date: new Date(2022,1,13)},
{may_id: "morocca", health: 1, date: new Date(2022,1,15)},
]
Insert cell
Insert cell
{
let aggData = d3.flatRollup(data, v => [d3.sum(v, d => d.count), d3.count(v, d => d.count)], d => d.date, d => d.sex)
aggData = aggData.map(d => d.flat())
return aggData.map(([lat, lng, requests, completed]) => ({lat, lng, requests, completed}));
}
Insert cell
Insert cell
// https://stackoverflow.com/questions/29017476/alternative-to-d3-ascending-d3-descending-for-sorting-undefined-values-to-b
function ascendingWithNaN(a, b) {
return isNaN(b) ? (isNaN(a) ? 0 : 1) // put NaN at the end
: a > b ? 1
: a < b ? -1
: a <= b ? 0
: NaN;
}
Insert cell
function descendingWithNaN(a, b) {
return isNaN(b) ? (isNaN(a) ? 0 : -1) // put NaN at the end
: a > b ? -1
: a < b ? 1
: a <= b ? 0
: NaN;
}
Insert cell
xyz = [15, 77, 354, 17, NaN, 35, 17, NaN, 8, 28]
Insert cell
xyz.sort(ascendingWithNaN)
Insert cell
Insert cell
endDate = new Date(2022, 10, 9)
Insert cell
movingWindow = d3.timeDay.every(2).range(d3.timeDay.offset(endDate, -14), endDate)
Insert cell
d3.timeDay.offset(endDate, -7)
Insert cell
abc = movingWindow.filter(d => d >= d3.timeDay.offset(endDate, -7))
Insert cell
fgh = movingWindow.map(d => pastWeekFilter(d))
Insert cell
Insert cell
<svg xmlns="http://www.w3.org/2000/svg" width="32px" height="32px">
<circle cx="16" cy="16" r="16" fill="#369040" />
</svg>
Insert cell
weekdayService = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
Insert cell
hours = d3.range(6,20);
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more