Public
Edited
Apr 27, 2023
Paused
9 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dms = {
let dimensions = {
width: width,
height: width * 0.6,
marginTop: 50,
marginLeft: 50
};

dimensions.marginBottom = dimensions.marginTop;
dimensions.marginRight = dimensions.marginLeft;

dimensions.chartWidth =
dimensions.width - dimensions.marginLeft - dimensions.marginRight;
dimensions.chartHeight =
dimensions.height - dimensions.marginTop - dimensions.marginBottom;

return dimensions;
}
Insert cell
Insert cell
timeParserYear = d3.timeParse("%Y")
Insert cell
timeFormatterYear = d3.timeFormat("%Y")
Insert cell
timeParserDate = function(string) {
if (string.includes("/")) {
return d3.timeParse("%m/%d/%Y")(string);
} else if (string.includes("-")) {
return d3.timeParse("%Y-%m-%d")(string);
} else {
throw `Here's how your date is formatted: ${
string.length > 0 ? string : "IT'S BLANK 😭"
}. Good luck with that, my dude.`;
// return undefined;
}
}
Insert cell
timeParserDate("asdfasdfasdf")
Insert cell
nameFormatter = function(first, middle, last, suffix) {
let name = "";

first != " " && first.length > 0 ? (name = name + first) : (name = name);
middle != " " && middle.length > 0
? (name = name + " " + middle)
: (name = name);
last != " " && last.length > 0 ? (name = name + " " + last) : (name = name);
suffix != " " && suffix.length > 0
? (name = name + " " + suffix)
: (name = name);

return name;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = {
const attachment = await FileAttachment("judges.csv").text();
const dataRaw = d3.csvParse(attachment);

// Filter out judges that were never confirmed by the Senate
const dataFilteredConfirmationDate = dataRaw.filter(
d => d["Confirmation Date (1)"].length != 0
);

// Add "terms" object to each judge
const dataProcessed = dataFilteredConfirmationDate.map(d => {
const terms = [];

for (let i = 1; i <= 6; i++) {
let termSingle = {};

if (d[`Court Type (${i})`].length > 0) {
termSingle["CourtType"] = d[`Court Type (${i})`];
termSingle["CourtName"] = d[`Court Name (${i})`];
termSingle["President"] = d[`Appointing President (${i})`];
termSingle["Party"] = d[`Party of Appointing President (${i})`];
termSingle["ConfirmationYear"] =
d[`Confirmation Date (${i})`].length > 0
? timeFormatterYear(timeParserDate(d[`Confirmation Date (${i})`]))
: "";
termSingle["TerminationYear"] =
d[`Termination Date (${i})`].length > 0
? timeFormatterYear(timeParserDate(d[`Termination Date (${i})`]))
: d[`Termination Date (${i})`].length <= 0 &&
d[`Senior Status Date (${i})`].length > 0
? timeFormatterYear(timeParserDate(d[`Senior Status Date (${i})`]))
: "";

if (d[`Confirmation Date (${i})`].length) {
termSingle["ConfirmationDate"] = timeParserDate(
d[`Confirmation Date (${i})`]
);
}

terms.push(termSingle);
}
}

d["TermsServed"] = terms;

return {
NID: d["nid"],
Name: nameFormatter(
d["First Name"],
d["Middle Name"],
d["Last Name"],
d["Suffix"]
),
NameParts: {
NameFirst: d["First Name"],
NameMiddle: d["Middle Name"],
NameLast: d["Last Name"],
NameSuffix: d["Suffix"]
},
Gender: d["Gender"],
Race: d["Race or Ethnicity"],
Terms: d["TermsServed"],
FirstYear: +d["TermsServed"][0]["ConfirmationYear"],
LastYear:
d["TermsServed"][d["TermsServed"].length - 1]["TerminationYear"]
.length > 0
? +d["TermsServed"][d["TermsServed"].length - 1]["TerminationYear"]
: 2020
};
});

return dataProcessed;
// return dataProcessed.filter(d => +d["FirstYear"] >= 1900);
}
Insert cell
data.find(
d =>
d["NameParts"]["NameLast"] == "Roberts" &&
d["NameParts"]["NameFirst"] == "John"
)
Insert cell
Insert cell
dataGenderActive = {
const activeJudgesPerYear = [];

years.forEach(year => {
data.forEach(judge => {
if (judge["FirstYear"] <= year && year <= judge["LastYear"]) {
let tempObj = { NID: "", Name: "", Year: year, Gender: "" };

tempObj["NID"] = judge["NID"];
tempObj["Name"] = judge["Name"];
tempObj["Gender"] = judge["Gender"];

activeJudgesPerYear.push(tempObj);
}
});
});

return d3.group(activeJudgesPerYear, d => d["Year"], d => d["Gender"]);
}
Insert cell
dataGenderActiveProcessor = function(data) {
return Array.from(data, ([key, values]) => {
let obj = Object.fromEntries(values.entries());

obj.Male = obj["Male"] === undefined ? 0 : obj["Male"].length;
obj.Female = obj["Female"] === undefined ? 0 : obj["Female"].length;
obj.Year = key;

return obj;
});
}
Insert cell
dataGenderActiveSeries = {
const stack = d3
.stack()
.keys(["Male", "Female"])
.order(d3.stackOrderReverse)
.offset(d3.stackOffsetExpand);

return stack(dataGenderActiveProcessor(dataGenderActive));
}
Insert cell
Insert cell
dataGenderConfirmations = {
return d3.group(
data
.filter(d => +d["FirstYear"] >= startingYear)
.sort((a, b) => d3.ascending(a["FirstYear"], b["FirstYear"])),
d => d["FirstYear"],
d => d["Gender"]
);
}
Insert cell
dataGenderConfirmationsProcessor = function(data) {
return Array.from(data, ([key, values]) => {
let obj = Object.fromEntries(values.entries());

obj.Male = obj["Male"] === undefined ? 0 : obj["Male"].length;
obj.Female = obj["Female"] === undefined ? 0 : obj["Female"].length;
obj.Year = key;

return obj;
});
}
Insert cell
dataGenderConfirmationsSeries = {
const stack = d3
.stack()
.keys(["Male", "Female"])
.order(d3.stackOrderReverse)
.offset(d3.stackOffsetNone);

return stack(dataGenderConfirmationsProcessor(dataGenderConfirmations));
}
Insert cell
dataGenderConfirmationsSeriesProportional = {
const stack = d3
.stack()
.keys(["Male", "Female"])
.order(d3.stackOrderReverse)
.offset(d3.stackOffsetExpand);

return stack(dataGenderConfirmationsProcessor(dataGenderConfirmations));
}
Insert cell
Insert cell
time = d3
.scaleTime()
// .domain([timeParserYear(1789 - 1), timeParserYear("2020")])
.domain([timeParserYear(startingYear - 1), timeParserYear(2020)])
// .domain([timeParserYear(2008 - 1), timeParserYear(2020)])
.range([0, dms.chartWidth])
Insert cell
timeZoomed = d3
.scaleTime()
.domain([timeParserYear(startingYear - 1), timeParserYear(2020)])
.range([0, dms.chartWidth])
Insert cell
judges = d3
.scaleLinear()
.domain([0, 150])
.range([dms.chartHeight, 0])
Insert cell
percentage = d3
.scaleLinear()
.domain([0, 100])
.range([0, dms.chartHeight])
Insert cell
color = d3
.scaleOrdinal()
.domain(["Male", "Female"])
.range(["#d6d6d6", "#ff5e63"])
Insert cell
Insert cell
area = d3
.area()
.x(d => time(timeParserYear(d.data.Year)))
.y0(d => percentage(d[0]))
.y1(d => percentage(d[1]))
Insert cell
annotationV = function(x) {
return `M ${
x + 0.5 /* 👈 Adding the stroke width of the annotation line here*/
} ${-10 /* 👈 Adding the offset above the chart here*/} v ${dms.chartHeight +
10}`;
}
Insert cell
annotationH = function(y) {
return `M 0 ${y + 0.5} h ${dms.chartWidth}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
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