Public
Edited
Jul 12, 2022
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vlChart = {
let data = weatherByDate;

const maxDateWithValue = new Date(currentDate);
const aWeekBeforeMax = maxDateWithValue - 7 * 24 * 3600000;
const thresholdBeforeMax = maxDateWithValue - threshold * 24 * 3600000;

data = weatherByDate.map(d => ({
...d,
Confidence:
d.key < thresholdBeforeMax
? 1
: (maxDateWithValue - d.key) / (threshold * 24 * 3600000) / 2
}));

const gridCondition = {
condition: {
test: "+timeFormat(datum.value, '%d') <= 7",
value: []
},
value: [1, 5]
};

const base = vl.markBar({ tooltip: true }).encode(
vl
.x()
.fieldT("key")
.timeUnit("yearmonthdate")
.title("Date")
.axis({
gridDash: gridCondition,
tickCount: "week",
tickDash: gridCondition,
labelAlign: "left",
labelExpr:
"[timeFormat(datum.value, '%d'), +timeFormat(datum.value, '%d') <= 7 ? timeFormat(datum.value, '%b') : '']",
labelOffset: 4,
labelPadding: -24,
tickSize: 30
}),
vl
.y()
.fieldQ("value")
.title(attrLabels[attrSelected]),
vl
.opacity()
.fieldQ("Confidence")
.scale({ domain: [0, 1], range: [0, 1] })
.legend(
width > 600
? {
format: "%",
symbolFillColor: "firebrick",
symbolStrokeColor: "firebrick"
}
: null
)
);

const bar = base.encode(
vl
.color()
.fieldQ("value")
.title(attrLabels[attrSelected])
.legend(width > 600)
.scale({ scheme: "lightgreyteal" })
);

const line = base
.markLine({
color: "firebrick",
size: 2,
interpolate: "basis"
})
.transform(vl.window(vl.mean("value").as("rolling_mean")).frame([-days, 0]))
.encode(
vl.y().fieldQ("rolling_mean"),
vl
.color()
.value("firebrick")
.legend(
width > 600
? {
format: "%",
symbolFillColor: "steelblue",
symbolStrokeColor: "steelblue"
}
: null
)
);

return vl
.layer(bar, line)
.data(data)
.width(width - (width > 600 ? 200 : 50))
.height(400);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// There are 1,461 records for Seattle, which causes the chart to render slowly
// Filter out older dates/records to help the animation progress more quickly
weatherByDate = weather
.filter(d => d.date >= dateParse(earliestDate) && d.location === "Seattle")
.map(d => ({
value: +d[attrSelected],
key: d.date
}))
Insert cell
// There are more locations than Seattle, so we need to filter for Seattle
// when we produce weatherByDate in the cell above
weather.filter(d => d.date.toString() == new Date('2015-05-03').toString())
Insert cell
weatherDatesExtent = d3.extent(weather.map(d => d.date))
Insert cell
d3.extent(weather.map(d => d.precipitation))
Insert cell
d3.extent(weather.map(d => d.temp_max))
Insert cell
d3.extent(weather.map(d => d.temp_min))
Insert cell
d3.extent(weather.map(d => d.wind))
Insert cell
attrLabels = ({
wind: "Wind",
temp_max: "Temp (Max)",
temp_min: "Temp (Min)",
precipitation: "Precipitation"
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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