Published
Edited
Apr 6, 2021
Insert cell
md`# A1`
Insert cell
md`
Seattle gets a bad rap for being a gloomy place, but how much sun does it really get compared to other cities in the US?

The graph below compares the hours of sunshine each of the cities receives per month, highlighting Seattle's hours. From the graph it's clear that Seattle's reputation is well deserved as indeed, except for a couple of months during the summer it is the city that receives the least amount of hours of sunshine.

For this graph, since the hours of sunshine is the most important information I choose to represent it using the y position in the graph, and the month in the x position, with a different series for each city; overall this makes it easy to compare the amount of sunshine each city received per month. I chose to use a line mark as it makes it easier for a reader to follow how each series advances (I considered using points, but the series got lost).

To emphasize the point that Seattle is the city we are interested on, its value are highlighted by making the stroke width thicker and applying transparency to the other cities.

Months are sorted by their number value (as opposed to alphabetically) to match a reader's expectation.

Finally, the value of the city with the minimum hours of sunshine for each month is highlighted with a point mark, also to emphasize the point that most months Seattle has the least value.
`
Insert cell
import {data} from '@uwdata/hours-of-sunshine';
Insert cell
data
Insert cell
import {vl} from '@vega/vega-lite-api-v5';
Insert cell
{
const other = vl.markLine({ opacity: 0.3 })
.data(data)
.encode(
vl.x()
.fieldO('month')
.sort({field: 'monthnum'})
.axis({title: 'Month'}),
vl.y()
.fieldQ('sunshine'),
vl.color()
.fieldN('city'),
vl.tooltip(['city', 'sunshine'])
)

.width(700);

const seattle = vl.markLine({ strokeWidth: 5 })
.data(data)
.transform(
vl.filter('datum.city == "Seattle"')
)
.encode(
vl.x().fieldO('month')
.sort({field: 'monthnum'})
,
vl.y().fieldQ('sunshine'),
vl.color().fieldN('city')
);

const points = vl.markPoint({ size: 120, filled: true })
.data(data)
.transform(
vl.joinaggregate({ op: 'min', field: 'sunshine', as: 'minSunshine' })
.groupby('month'),
// vl.filter('datum.city == "Seattle"'),
vl.filter('datum.sunshine == datum.minSunshine')
)
.encode(
vl.x().fieldO('month').sort({field: 'monthnum'}),
vl.y().fieldQ('minSunshine').axis({title: 'Hours of Sunshine'}),
vl.color().fieldN('city')
);

// return points.render();
return vl.layer(other, seattle, points).title({text: "A gloomy Seattle?", fontSize: 20}).render();
// return html`<pre>${JSON.stringify(other.toObject(), 0, 2)}</pre>`; // format JSON data
}
Insert cell
{
const map = vl.markBar({opacity: 1, color: 'lightgray'})
.data(data)
.transform(
vl.aggregate({ op: 'sum', field: 'sunshine', as: 'totalSunshine' })
.groupby('city')
)
.encode(
vl.x().fieldN('city'),
// vl.latitude().fieldQ('lat'),
vl.y().fieldQ('totalSunshine'),
vl.tooltip(['city', 'totalSunshine'])
);

return map.render();
}
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