Public
Edited
Feb 26, 2024
Insert cell
Insert cell
CountyLiteracy = FileAttachment("county_literacy_numeracy.csv").csv({type: true})
Insert cell
SchoolExpenditure = FileAttachment("school_expenditure.csv").csv({type: true})
Insert cell
vl.markBar()
.data(CountyLiteracy)
.encode(
vl.x().fieldN('State').title('State'),
vl.y().fieldQ('Lit_P1').title('Proportion at Literacy Level 1'),
vl.tooltip([
vl.fieldN('State'),
vl.fieldQ('Lit_P1')
])
)
.width(600)
.height(400)
.render();
Insert cell
uniqueCounties = ['All', ...new Set(CountyLiteracy.map(d => d.County))];
Insert cell
{
const uniqueCounties = ['All', ...new Set(CountyLiteracy.map(d => d.County))];

// Dropdown menu for county selection
const selectedCounty = vl.param('selected_county')
.value('All') // Default value
.bind(vl.menu(uniqueCounties).name('Select County:')); // Dropdown menu

return vl.markBar()
.data(CountyLiteracy)
.params(selectedCounty)
.transform(
// Apply filtering based on the selected county if not 'All'
vl.filter('datum.County === selected_county || selected_county === "All"')
)
.encode(
vl.x().fieldN('State').title('State'),
vl.y().fieldQ('Lit_P1').title('Proportion at Literacy Level 1').aggregate('average'),
vl.tooltip([
vl.fieldN('State'),
vl.fieldQ('Lit_P1')
])
)
.width(window.innerWidth - 100) // Responsive width
.height(400)
.render();
}
Insert cell
usStatesGeoJSON = FileAttachment("gz_2010_us_040_00_500k.json").json()
Insert cell
{
const expenditureByState = new Map(SchoolExpenditure.map(d => [d.State, +d["Per pupil current spending (whole dollars)"]]));
const enrichedGeoJSON = usStatesGeoJSON.features.map(feature => {
const expenditure = expenditureByState.get(feature.properties.NAME); // get expenditure by state
return {
...feature,
properties: {
...feature.properties,
expenditure: expenditure
}
};
});

return vl.markGeoshape()
.data({ values: enrichedGeoJSON })
.encode(
vl.color().fieldQ('properties.expenditure').title('Per Pupil Spending ($)'),
// Example application: use the parameter to adjust the size encoding
vl.size().fieldQ('properties.expenditure'),
vl.tooltip([
{field: 'properties.NAME', type: 'nominal', title: 'State'},
{field: 'properties.expenditure', type: 'quantitative', title: 'Per Pupil Spending ($)'}
])
)
.project(vl.projection('albersUsa'))
.width(800)
.height(500)
.render();
}
Insert cell
{
const highlightSelection = vl.selectSingle()
.on('mouseover') // Trigger selection on mouseover
.clear('mouseout') // Clear selection on mouseout
.encodings(['color']) // Apply selection to color encoding
.init(null); // Initialize selection to be empty
const expenditureByState = new Map(SchoolExpenditure.map(d => [d.State, +d["Per pupil current spending (whole dollars)"]]));
const enrichedGeoJSON = usStatesGeoJSON.features.map(feature => {
const expenditure = expenditureByState.get(feature.properties.NAME); // get expenditure by state
return {
...feature,
properties: {
...feature.properties,
expenditure: expenditure
}
};
});

return vl.markGeoshape()
.data({ values: enrichedGeoJSON })
.params(highlightSelection) // Apply the selection
.encode(
vl.color().fieldQ('properties.expenditure').title('Per Pupil Spending ($)'),
vl.stroke().value('gray'), // Default stroke color
vl.strokeWidth().if(highlightSelection, vl.value(3)).value(0), // Thicker stroke for selected shapes
vl.tooltip([
{ field: 'properties.NAME', type: 'nominal', title: 'State' },
{ field: 'properties.expenditure', type: 'quantitative', title: 'Per Pupil Spending ($)' }
])
)
.project(vl.projection('albersUsa'))
.width(800)
.height(500)
.render();
}

Insert cell
{
const metricParam = vl.param('metricParam')
.value("Per pupil current spending (whole dollars)") // default value
.bind(vl.menu([
"Per pupil current spending (whole dollars)",
"Capital outlay"
]).name('Choose a metric to display:')); // dropdown menu

// Assuming usStatesGeoJSON and SchoolExpenditure are already defined and loaded
const enrichedGeoJSON = usStatesGeoJSON.features.map(feature => {
// Example logic to dynamically select metric based on metricParam's value
const metricValue = new Map(SchoolExpenditure.map(d => [d.State, +d[metricParam.value]])).get(feature.properties.NAME);
return {
...feature,
properties: {
...feature.properties,
metricValue: metricValue // dynamically add selected metric's value
}
};
});

// Create and render the Vega-Lite map visualization
const mapVisualization = vl.markGeoshape()
.params(metricParam) // use the parameter in your visualization
.data({values: enrichedGeoJSON})
.encode(
vl.color().fieldQ('properties.metricValue').title(metricParam.value),
vl.tooltip([
vl.fieldN('properties.NAME'),
vl.fieldQ('properties.metricValue')
])
)
.project(vl.projection('albersUsa'))
.width(800)
.height(500)
.render()
}

Insert cell
import {vl} from "@vega/vega-lite-api-v5"
Insert cell
import {printTableTypes} from "@jonfroehlich/data-utilities"
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more