Public
Edited
Mar 22, 2023
Insert cell
d3 = require('d3@7', 'd3-geo@2', 'd3-dsv', 'd3-selection', 'd3-simple-slider', 'd3-simple-slider@1');
Insert cell
topojson = require("topojson-client@3")
Insert cell
commaSeparated = d3.format(",")
Insert cell
teacherSalary2015 = Object.assign(new Map(d3.csvParse(await FileAttachment("teacherSalary2015.csv").text(), ({state, avg_teacher_salary}) => {
console.log(state, avg_teacher_salary);
return [state, +avg_teacher_salary];
})), {title: "Average Allocated Funding for Teacher Salary By State in 2015"});
Insert cell
teacherSalary2016 = Object.assign(new Map(d3.csvParse(await FileAttachment("teacherSalary2016.csv").text(), ({state, avg_teacher_salary}) => {
console.log(state, avg_teacher_salary);
return [state, +avg_teacher_salary];
})), {title: "Average Allocated Funding for Teacher Salary By State in 2016"});
Insert cell
teacherSalary2017 = Object.assign(new Map(d3.csvParse(await FileAttachment("teacherSalary2017@3.csv").text(), ({state, avg_teacher_salary}) => {
console.log(state, avg_teacher_salary);
return [state, +avg_teacher_salary];
})), {title: "Average Allocated Funding for Teacher Salary By State in 2017"});

Insert cell
teacherSalary2018 = Object.assign(new Map(d3.csvParse(await FileAttachment("teacherSalary2018@6.csv").text(), ({state, avg_teacher_salary}) => [state, +avg_teacher_salary])), {title: "Average Allocated Funding for Teacher Salary By State in 2018"})
Insert cell
// {
// const values2015 = Array.from(teacherSalary2015.values()); // get an array of values from the Map object
// const minSalary2015 = d3.min(values2015);
// const maxSalary2015 = d3.max(values2015);
// }
Insert cell
// minSalary2015 = d3.min(Array.from(teacherSalary2015.values()));
Insert cell
// maxSalary2015 = d3.max(Array.from(teacherSalary2015.values()));
Insert cell
// {
// const values2015 = Array.from(teacherSalary2015.values());
// const minSalary2015 = d3.min(values2015);
// var minState2015;
// teacherSalary2015.forEach((value, key) => {
// if (value === minSalary2015) {
// minState2015 = key;
// }
// });
// return `${minState2015}, ${minSalary2015}`
// }
Insert cell
// TopoJSON Map Data for the United States
us = FileAttachment("states-albers-10m.json").json()
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
import {select} from "@jashkenas/inputs"
Insert cell
import {Scrubber} from "@mbostock/scrubber"
Insert cell
projection = d3.geoAlbersUsa().scale(1300).translate([487.5, 305])
Insert cell
path = d3.geoPath()
Insert cell
states = topojson.feature(us, us.objects.states, (a, b) => a !== b);
Insert cell
nations = topojson.feature(us, us.objects.nation);
Insert cell
d3_annotation = require("https://cdnjs.cloudflare.com/ajax/libs/d3-annotation/2.3.0/d3-annotation.min.js")
Insert cell
Insert cell
Insert cell
map = (us) => {
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, 2800, height]);

// const teacherSalaryByState = {};
// teacherSalary2018.forEach(d => (teacherSalaryByState[d[0]] = +d[1]));
// const str = "Average Teacher Salary By State in " + time.getUTCFullYear();
const str = "Average Allocated Funding for Teacher Salary By State in " + yearFilter;

// Color Schema
let color;

if (str === "Average Allocated Funding for Teacher Salary By State in 2015") {
// TO EDIT LEGEND
const salaryLegend = [2000000, 3000000, 6000000, 7000000, 12000000, 15000000, 30000000, 40000000];
// const salaryLegend = [2000000, 6000000, 12000000, 30000000];
// const formattedSalaryLegend = salaryLegend.map(d => `$${commaSeparated(d)}`);
color = d3.scaleThreshold()
.domain(salaryLegend)
// .range(d3.schemeBlues[5]);
.range(d3.schemeBlues[8]);
}
if (str === "Average Allocated Funding for Teacher Salary By State in 2016") {
// TO EDIT LEGEND
const salaryLegend = [2000000, 3000000, 6000000, 7000000, 12000000, 15000000, 30000000, 40000000];
// const salaryLegend = [3000000, 7000000, 15000000, 40000000];
// const formattedSalaryLegend = salaryLegend.map(d => `$${commaSeparated(d)}`);
color = d3.scaleThreshold()
.domain(salaryLegend)
.range(d3.schemeBlues[8]);
}
if (str === "Average Allocated Funding for Teacher Salary By State in 2017") {
const salaryLegend = [2000000, 3000000, 6000000, 7000000, 12000000, 15000000, 30000000, 40000000];
// const salaryLegend = [2000000, 6000000, 12000000, 30000000];
// const formattedSalaryLegend = salaryLegend.map(d => `$${commaSeparated(d)}`);
color = d3.scaleThreshold()
.domain(salaryLegend)
.range(d3.schemeBlues[8]);
}
if (str === "Average Allocated Funding for Teacher Salary By State in 2018") {
// const salaryLegend = [`N/A`, 2000000, 3000000, 6000000, 7000000, 12000000, 15000000, 30000000, 40000000];
const salaryLegend = [2000000, 3000000, 6000000, 7000000, 12000000, 15000000, 30000000, 40000000];
// const salaryLegend = [3000000, 7000000, 15000000, 40000000];
const formattedSalaryLegend = salaryLegend.map(d => `$${commaSeparated(d)}`);
color = d3.scaleThreshold()
.domain(salaryLegend)
.range(d3.schemeBlues[8])
}

// Map Title
svg.append("text")
.attr("x", width / 5)
.attr("y", 0)
.attr("text-anchor", "start")
.style("font-size", "30px")
.style("font-weight", "bold")
.text(str);
// Baseline Map of Nations
svg.append("path")
.datum(nations)
.attr("fill", "black")
.attr("stroke", "none")
.attr("d", path);

// Baseline Map of States
svg.append("path")
.datum(states)
.attr("fill", "none")
.attr("stroke", "none")
.attr("d", path);
// Add Color Schema Legend
svg.append("g")
.attr("transform", "translate(1000,30)")
.append(function(d) {
if (str=="Average Allocated Funding for Teacher Salary By State in 2015"){
return legend({color, title: teacherSalary2015.title + ` in dollars($)`, width: 600});
}
if (str=="Average Allocated Funding for Teacher Salary By State in 2016"){
return legend({color, title: teacherSalary2016.title + ` in dollars($)`, width: 600});
}
if (str=="Average Allocated Funding for Teacher Salary By State in 2017"){
return legend({color, title: teacherSalary2017.title + ` in dollars($)`, width: 600});
}
if (str=="Average Allocated Funding for Teacher Salary By State in 2018"){
return legend({color, title: teacherSalary2018.title + ` in dollars($)`, width: 600});}
})

// SVG Show or Hide State Information
svg.append("g")
.selectAll("path")
.data(states.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", function (d) {
if (str === "Average Allocated Funding for Teacher Salary By State in 2015") {
return color(teacherSalary2015.get(d.properties.name));
} else if (str === "Average Allocated Funding for Teacher Salary By State in 2016") {
return color(teacherSalary2016.get(d.properties.name));
} else if (str === "Average Allocated Funding for Teacher Salary By State in 2017") {
return color(teacherSalary2017.get(d.properties.name));
} else if (str === "Average Allocated Funding for Teacher Salary By State in 2018") {
return color(teacherSalary2018.get(d.properties.name));
}
})
.attr("stroke", "white")
.on("mouseover", (event, d) => {
const [x, y] = d3.pointer(event);
const padding = 5;
const lengthOfStateName = d.properties.name.length * 10
const name = d.properties.name;

d3.select(event.currentTarget)
.attr("stroke", "black")
.raise();

if (str === "Average Allocated Funding for Teacher Salary By State in 2015") {
const salary = teacherSalary2015.get(name);
// const minSalary = d3.min(teacherSalary2015.get(name));
// const maxSalary = d3.max(teacherSalary2015.get(name));
tooltip.select("text")
.text(null)
.append("tspan")
.text(name)
.attr("font-size", "25px")
.append("tspan")
.attr("dy", "1.2em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(salary ? `2015 Average Allocated Funding for Teacher Salary: $${commaSeparated(salary)}` : "No 2015 Average Allocated Funding for Teacher Salary Available")
}

if (str === "Average Allocated Funding for Teacher Salary By State in 2016") {
const salary = teacherSalary2016.get(name);
tooltip.select("text")
.text(null)
.append("tspan")
.text(name)
.attr("font-size", "25px")
.append("tspan")
.attr("dy", "1.2em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(salary ? `2016 Average Allocated Funding for Teacher Salary: $${commaSeparated(salary)}` : "No 2016 Average Allocated Funding for Teacher Salary Available")
}
if (str === "Average Allocated Funding for Teacher Salary By State in 2017") {
const salary = teacherSalary2017.get(name);
tooltip.select("text")
.text(null)
.append("tspan")
.text(name)
.attr("font-size", "25px")
.append("tspan")
.attr("dy", "1.2em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(salary ? `2017 Average Allocated Funding for Teacher Salary: $${commaSeparated(salary)}` : "No 2017 Average Allocated Funding for Teacher Salary Available")
}

if (str === "Average Allocated Funding for Teacher Salary By State in 2018") {
const salary = teacherSalary2018.get(name);
tooltip.select("text")
.text(null)
.append("tspan")
.text(name)
.attr("font-size", "25px")
.append("tspan")
.attr("dy", "1.2em")
.attr("font-size", "20px")
.attr("x", 20)
.attr("y", 25)
.attr("text-anchor", "start")
.text(salary ? `2018 Average Allocated Funding for Teacher Salary: $${commaSeparated(salary)}` : "No 2018 Average Allocated Funding for Teacher Salary Available")
}
const textLength = tooltip.select('text').node().getComputedTextLength();

tooltip.select("rect")
.attr("width", textLength)
.attr("height", 80)
tooltip.attr("transform", `translate(${x},${y})`);
tooltip.select("rect")
.attr("width", textLength)
.attr("x")
tooltip.style("display", "block");
})
.on("mouseout", (event, d) => {
tooltip.style("display", "none")

d3.select(event.currentTarget)
.attr("stroke", "white")
.lower();
});

const infoWindow = svg
.append("rect")
.attr("transform", "translate(1000,100)")
.attr("width", 622)
.attr("height", height)
.attr("fill", "white")
.attr("stroke", "black")

infoWindow.append("rect")
.attr("width", 600)
.attr("height", height)
.attr("fill", "white")
.attr("stroke", "black");
infoWindow.append("text")
.attr("x", 1000)
.attr("y", 300)
.text("Hello this is the info window text");

const values2015 = Array.from(teacherSalary2015.values());
const minSalary2015 = d3.min(values2015);

let minState2015;
teacherSalary2015.forEach((value, key) => {
if (value === minSalary2015) {
minState2015 = key;
}
});

const annotationGroup = svg.append("g")
.attr("transform", "translate(50,50)")

annotationGroup.append("rect")
.attr("width", 150)
.attr("height", 50)
.attr("fill", "white")
.attr("stroke", "black");

annotationGroup.append("text")
.attr("x", 10)
.attr("y", 30)
.attr("font-size", "16px")
.attr("text-anchor", "start")
.text(`LOWEST: ${minSalary2015}`);
// .text(`Lowest teacher salary: ${minState2015}, ${minSalary2015}`);

annotationGroup.attr("transform", "translate(50,50)");
const rect = svg
.append("rect")
.attr("id", "tooltip-box")
.attr("height", 80)

const stateName = svg.append("text")
.attr("y", 20)
.attr("stroke", "black")
.attr("alignment-baseline", "middle");

// Tooltip
const tooltip = svg
.append("g")
.attr("class", "tooltip")
.style("display", "none");

tooltip.append("rect")
.attr("width", 100)
.attr("height", 80)
.attr("fill", "white")
.attr("stroke", "black")
tooltip.append("text")
.attr("y", 25)
.attr("x", 20)
.attr("text-anchor", "start")
.text("");
return svg.node();
}
Insert cell
times = d3.utcYears(Date.UTC(2010), Date.UTC(2019))
Insert cell
time.getUTCFullYear()
Insert cell
// viewof dd1 = select({
// title: md `### Teacher Salary By State`,
// description: "Select a Report Map Model",
// options: ["Total Average Teacher Salary By State in 2010-2018", "Average Teacher Salary By State in 2010", "Average Teacher Salary By State in 2011", "Average Teacher Salary By State in 2012", "Average Teacher Salary By State in 2013", "Average Teacher Salary By State in 2014", "Average Teacher Salary By State in 2015", "Average Teacher Salary By State in 2016", "Average Teacher Salary By State in 2017", "Average Teacher Salary By State in 2018"],
// value: "Total State Allocated Funding for Teacher Salaries"
// })
Insert cell
Insert cell
Insert cell
map(us)
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