Published
Edited
May 15, 2019
Fork of Project Code
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dataGeneral = d3.csv("https://gist.githubusercontent.com/nbailey/95ad116b50e7b7cbe02a8e2dac626922/raw/e3d08f6b6c829885d997231988a27aa272f117cb/sevis_gen_201808")
Insert cell
dataStem = d3.csv("https://gist.githubusercontent.com/nbailey/95ad116b50e7b7cbe02a8e2dac626922/raw/e3d08f6b6c829885d997231988a27aa272f117cb/sevis_stem_201808")
Insert cell
Insert cell
Insert cell
dataStem.columns
Insert cell
stemCountries = z.unique(z.getCol("CoC", dataStem)).sort();
Insert cell
allCountries = z.unique(z.getCol("Country of Citizenship", dataGeneral)).sort();
Insert cell
states = z.unique(z.getCol("State", dataStem)).sort();
Insert cell
stateAbbrevs = dataGeneral.columns.slice(17,72);
Insert cell
stemByCountry = z.groupBy(d => d["CoC"], dataStem)
Insert cell
countryStem = {
let output = {};
z.gbSum("Count of Active STEM Students", stemByCountry).forEach(row => (output[row.group] = row.sum));
return output;
}
Insert cell
countryTotal = {
let countryStudents = {};
dataGeneral.forEach(row => (countryStudents[row["Country of Citizenship"]] = +row["# of Active Students"]));
return countryStudents
}
Insert cell
countryPctStem = {
let output = {};
for (var i in allCountries) {
let country = allCountries[i];
if (!stemCountries.includes(country)) {
output[country] = 0;
} else {
output[country] = countryStem[country] / countryTotal[country];
}
}
return output;
}
Insert cell
countryStateStem = {
let output = [];
for (var i in stemCountries) {
let country = stemCountries[i];
let countryStem = stemByCountry[country];
// output[country] = z.groupBy(d => d["Abbreviation"], countryStem);
output[country] = z.gbSum("Count of Active STEM Students", z.groupBy(d => d["Abbrv"], countryStem));
}
return output;
}
Insert cell
z.filter(d => (d.group == "TX"),countryStateStem["CHINA"])[0].sum
Insert cell
countryStateTotals = {
let output = {};
for (var i in allCountries) {
let country = allCountries[i];
let countryData = z.filter(d => (d["Country of Citizenship"] == country), dataGeneral);
// Keep columns 17:72, the data of how many students from that country are in each state
output[country] = z.pickCols(Object.keys(countryData[0]).slice(17,72), countryData)[0];
}
return output;
}
Insert cell
countryStateStemPct = {
let output = {};
for (var i in allCountries) {
let country = allCountries[i];
let stemPct = {};
let countryHasStem = stemCountries.includes(country);
let countryStemData = undefined;
let countryStemStates = undefined;
if (countryHasStem) {
countryStemData = countryStateStem[country];
countryStemStates = z.getCol("group", countryStemData)
}
let countryGenData = countryStateTotals[country];
let countryGenStates = Object.keys(countryGenData);
for (var j in stateAbbrevs) {
let state = stateAbbrevs[j];
if (countryHasStem) {
if (countryStemStates.includes(state)) {
let numStem = +z.filter(d => d.group == state, countryStemData)[0].sum;
let numStudents = +countryGenData[state];
// Assuming that STEM is a subset of the number of students
if (numStudents > 0) {
stemPct[state] = numStem / numStudents;
} else {
stemPct[state] = NaN;
}
// stemPct[state] = numStem / (numStem + numStudents);
} else {
stemPct[state] = 0;
}
} else {
stemPct[state] = 0;
}
}
output[country] = stemPct;
}
return output;
}
Insert cell
countryStateStemNumbers = {
let output = {};
for (var i in allCountries) {
let country = allCountries[i];
let stateStem = {};
let countryHasStem = stemCountries.includes(country);
let countryStemData = undefined;
let countryStemStates = undefined;
if (countryHasStem) {
countryStemData = countryStateStem[country];
countryStemStates = z.getCol("group", countryStemData)
}
let countryGenData = countryStateTotals[country];
let countryGenStates = Object.keys(countryGenData);
for (var j in stateAbbrevs) {
let state = stateAbbrevs[j];
if (countryHasStem) {
if (countryStemStates.includes(state)) {
let numStem = +z.filter(d => d.group == state, countryStemData)[0].sum;
stateStem[stateIDMap[state]] = numStem;
} else {
stateStem[stateIDMap[state]] = 0;
}
} else {
stateStem[stateIDMap[state]] = 0;
}
}
output[country] = stateStem;
}
return output;
}
Insert cell
countryStateStudentNumbers[countryOfInterest][11]
Insert cell
countryStateStudentNumbers = {
let output = {};
for (var i in allCountries) {
let country = allCountries[i];
let stateStudents = {};

let countryHasStem = stemCountries.includes(country);
let countryStemData = undefined;
let countryStemStates = undefined;
if (countryHasStem) {
countryStemData = countryStateStem[country];
countryStemStates = z.getCol("group", countryStemData)
}
let countryGenData = countryStateTotals[country];
let countryGenStates = Object.keys(countryGenData);
for (var j in stateAbbrevs) {
let state = stateAbbrevs[j];
if (countryHasStem) {
if (countryGenStates.includes(state)) {
let numStudents = +countryGenData[state];
stateStudents[stateIDMap[state]] = numStudents;
} else {
stateStudents[stateIDMap[state]] = 0;
}
} else {
stateStudents[stateIDMap[state]] = 0;
}
}
output[country] = stateStudents;
}
return output;
}
Insert cell
countrySelector = html`<select id="countrySelect"></select>`
Insert cell
countryOfInterest = country_dropdown
Insert cell
// Will use this when not on Observable: https://www.electrictoolbox.com/javascript-add-options-html-select/
countrySelector.options[0] = new Option("test", 0)
Insert cell
stemPctByID = {
let output = {};
Object.keys(countryStateStemPct[country_dropdown]).forEach(function(d) {
output[stateIDMap[d]] = countryStateStemPct[country_dropdown][d];
})
return output;
}
Insert cell
// your code here
stemPctByState = {
let width = 960;
let height = 600;
// Create SVG
let svg = d3.select(DOM.svg(width, height));

let g = svg.append("g");
// Bind TopoJSON data
g.selectAll("path")
.data(topojson.feature(us, us.objects.states).features) // Bind TopoJSON data elements
.enter().append("path")
.attr("d", path)
.style("fill", d => pctColorScale(stemPctByID[d.id]))
.style("stroke", "black")
.on("mouseover", d => tooltip.style("visibility", "visible").text(d.id))
.on("mousemove", d => tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").html(stateNameMap[d.id] + ": <br/>" + (100 * stemPctByID[d.id]).toFixed(1) + "% STEM <br/>(" + countryStateStemNumbers[countryOfInterest][d.id] + " STEM students out of " + countryStateStudentNumbers[countryOfInterest][d.id] + " total)"))
.on("mouseout", d => tooltip.style("visibility", "hidden"));

return svg.node();
}
Insert cell
Insert cell
// your code here
{
let width = 960;
let height = 600;
// Create SVG
let svg = d3.select(DOM.svg(width, height));

let g = svg.append("g");
// Bind TopoJSON data
g.selectAll("path")
.data(topojson.feature(us, us.objects.states).features) // Bind TopoJSON data elements
.enter().append("path")
.attr("d", path)
.style("fill", d => numColorScale(countryStateStudentNumbers[countryOfInterest][d.id]))
.style("stroke", "black")
.on("mouseover", d => tooltip.style("visibility", "visible").text(d.id))
.on("mousemove", d => tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(stateNameMap[d.id] + ": " + countryStateStudentNumbers[countryOfInterest][d.id] + " students from " + countryOfInterest))
.on("mouseout", d => tooltip.style("visibility", "hidden"));

return svg.node();
}
Insert cell
path = d3.geoPath();
Insert cell
tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("font-family", "'Open Sans', sans-serif")
.style("font-size", "12px")
.style("z-index", "10")
.style("visibility", "hidden")
.style("background", "white")
.style("padding", "5px")
.style("width", "100px")
Insert cell
pctColorScale = d3.scaleQuantize()
.domain([0, 1])
.range(d3.schemePurples[9]);
Insert cell
numColorScale = d3.scaleQuantize()
.domain([0, d3.max(Object.values(countryStateStudentNumbers[countryOfInterest]))])
.range(d3.schemePurples[9]);
Insert cell
Insert cell
Insert cell
stateIDMap = {
let output = {};
for (let i in onlyStates) {
let state = onlyStates[i];
let abbreviation = z.unique(z.getCol("Abbrv", z.filter(row => row["State"] == state, dataStem)))[0]
output[abbreviation] = stateIDs[i];
}
return output;
}
Insert cell
stateNameMap = {
let output = {};
for (let i in onlyStates) {
let state = onlyStates[i];
output[stateIDs[i]] = state;
}
return output;
}
Insert cell
topojson.mesh(us, us.objects.states, (a, b) => a !== b)
Insert cell
md` ## Degree Level by Country`
Insert cell
dataGeneral.columns
Insert cell
vocational = z.deriveCol(row => +row["FLIGHT TRAINING"] + +row["LANGUAGE TRAINING"] + +row["OTHER VOCATIONAL SCHOOL"], dataGeneral);
Insert cell
newData = z.addCol("VOCATIONAL", vocational, dataGeneral)
Insert cell
series = d3.stack().keys(["ASSOCIATE", "BACHELOR'S", "MASTER'S", "DOCTORATE", "VOCATIONAL"])(degreesByCountry)
Insert cell
degreesByCountry = z.filter(r => r["Country of Citizenship"] == country_dropdown, newData);
Insert cell
margin = ({top: 10, right: 10, bottom: 20, left: 40})
Insert cell
Insert cell
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0)) //feeding function 'x' as a function
.call(g => g.selectAll(".domain").remove())
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg1 = d3.select(DOM.svg(width, height)); //pointing it to the DOM object

svg1.append("g")
.selectAll("g")
.data(series)
.join("g")
.attr("fill", d => color(d.key))
.selectAll("rect")
.data(d => d)
.join("rect")
.attr("x", (d, i) => x(d.data.year))
.attr("y", d => y(d[1])) //feeding y the data at index [1]
.attr("height", d => y(d[0]) - y(d[1]))
.attr("width", x.bandwidth());

svg1.append("g")
.call(xAxis);

svg1.append("g")
.call(yAxis);

svg1.append("g")
.call(legend);

return svg1.node();
}
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