Public
Edited
Dec 2, 2024
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
hospitals1 = await d3.csv("https://raw.githubusercontent.com/JamesYahnke/490Project/refs/heads/main/hospitals1.csv", d3.autoType) //download derived hospital data from github
Insert cell
idata = d3.json("https://gist.githubusercontent.com/dakoop/d06705a420fb348e7e03c7437bbfe4cb/raw/172303390752b7a224d876582043240ee9e9bd9b/il-counties.geojson"); //download illinois geodata with counties
Insert cell
ChiData = idata.features.filter(d => d.properties.COUNTY_NAM == "COOK"); //filter to just cook county
Insert cell
projection1 = d3.geoAlbersUsa().fitSize([400,300], ChiData[0]) //create projection centered around chicago
Insert cell
chicago_hospitals = sorted_hospitals.filter(d => d.county_name == "Cook") //filter to hospitals in just cook county
Insert cell
chicago = {
var plot = Plot.plot({
width: "400", //set width and height
height: "300",
projection: projection1, //use projection created earlier
color: { //set color
scheme: "Oranges",
type: "linear",
unknown: "gray", //no color label because we already have one
},
marks: [
Plot.geo(ChiData, {stroke: "black"}), //draw county outline
Plot.dot(chicago_hospitals, {x: "geo_long", y: "geo_lat", r: 5, fill: "PctHighlySatisfied", stroke: "black", strokeWidth: .5, sort: null}),
Plot.tip(chicago_hospitals, Plot.pointer({x: "geo_long", y: "geo_lat", title: (d) => `Name: ${d.name} \nCounty: ${d.county_name} \nWebsite: ${d.website} \nPercent of Patients Highly Satisfied: ${d.PctHighlySatisfied}`})) //create tooltip for each hospital
]
})
return plot;
}
Insert cell
plot = {
var plot = Plot.plot({
width: "500", //set width and height
height: "600",
projection: { type: "albers-usa", domain: idata}, //use albers-usa projection and pass geodata as domain
color: { //set color
scheme: "Oranges",
type: "linear",
unknown: "gray",
legend: true,
label: "Percent of patients highly satisfied"
},
marks: [
Plot.geo(idata, {stroke: "black"}), //draw state and counties outline
Plot.dot(sorted_hospitals, {x: "geo_long", y: "geo_lat", r: "TotalBeds", fill: "PctHighlySatisfied", stroke: "black", strokeWidth: .5, sort: null}), //draw a dot at each hospital location
Plot.tip(sorted_hospitals, Plot.pointer({x: "geo_long", y: "geo_lat", title: (d) => `Name: ${d.name} \nCounty: ${d.county_name} \nWebsite: ${d.website} \nPercent of Patients Highly Satisfied: ${d.PctHighlySatisfied}`})) //create tooltip for each hospital
]
})
return plot;
}
Insert cell
sorted_hospitals = hospitals1.sort((a,b) => b.TotalBeds - a.TotalBeds) //sort by total number of beds
Insert cell
{
const points = d3.select(plot).selectAll("circle").data(sorted_hospitals); //select all circles and assign data
const points1 = d3.select(chicago).selectAll("circle").data(chicago_hospitals); //select all circles and assign data
const bars = d3.select(stacked_bars).selectAll("rect"); //select all rects and assign data
let isClicked = false;
points.on("pointerover", function(event, d) { //on pointer hover
drawPie(d, svg1); //call drawPie function to draw pie chart
});

points.on('pointerout', function(event, d) { //on pointer off
svg1.selectAll("svg > *").remove(); //remove pie chart from svg
});

points1.on("pointerover", function(event, d) { //on pointer hover in chicago vis
drawPie(d, svg1); //call drawPie function to draw pie chart
});

points1.on('pointerout', function(event, d) { //on pointer off
svg1.selectAll("svg > *").remove(); //remove pie chart from svg
});

var selectedBars = []; //create array to store selected bars
bars.on("click", function(event, d) {
var id = d3.select(this).text().substring(0, 6); //get the id

var index = selectedBars.indexOf(id); //search for id in the selected list

if(index === -1) { //not already clicked
selectedBars.push(id); //add to selected list

bars.filter(function(d) { //highlight the whole bar
return (d3.select(event.currentTarget).text() == d3.select(this).text());
}).classed("highlight", true);
points.filter(function(d) { //highlight the point on the main map
return d.entity_id == id;
}).classed("highlight", true);
points1.filter(function(d) { //highlight the point on the chicago map
return d.entity_id == id;
}).classed("highlight", true);
}
else { //already clicked
selectedBars.splice(index, 1); //remove from selected list

bars.filter(function(d) { //unhighlight the whole bar
return (d3.select(event.currentTarget).text() == d3.select(this).text());
}).classed("highlight", false);
points.filter(function(d) { //unhighlight the point on the main map
return d.entity_id == id;
}).classed("highlight", false);
points1.filter(function(d) { //unhighlight the point on the chicago map
return d.entity_id == id;
}).classed("highlight", false);
}
});
}
Insert cell
function drawPie(hosp, svg1){
var data = [{name: "Medicaid", value: hosp.Medicaid},
{name: "Medicare", value: hosp.Medicare},
{name: "OtherPublic", value: hosp.OtherPublic},
{name: "PrivateInsurance", value: hosp.PrivateInsurance},
{name: "PrivatePay", value: hosp.PrivatePay},
{name: "CharityCare", value: hosp.CharityCare}];

// Chart dimensions
const width = 400;
const height = 400;
const radius = Math.min(width, height) / 2;
// Create a group element to put chart in
const group = svg1.append('g')
.attr('transform', `translate(${width / 2}, ${height / 2})`);
// Create a color scale
const color = d3.scaleOrdinal()
.domain(data.map(d => d.name))
.range(d3.schemeCategory10);
// Create the pie generator
const pie = d3.pie()
.value(d => d.value);
// Create the arc generator
const arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
// Bind data to pie slices
const slices = group.selectAll('path')
.data(pie(data))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', d => color(d.data.name))
.attr('stroke', 'white')
.style('stroke-width', '2px');
// Add labels to slices
group.selectAll('text')
.data(pie(data))
.enter()
.append('text')
.attr('transform', d => `translate(${arc.centroid(d)})`)
.text(d => d.data.name)
.style('font-size', '12px')
.style('fill', 'white');
}
Insert cell
svg1 = { //create svg for pie chart
var svg1 = d3.create("svg")
.attr("width", 400)
.attr("height", 400);
return svg1;
}
Insert cell
stacked_data = { //This cell creates a new array of data that formats it for the stacked bar chart by making a new entry for each type of payment
var stacked_data = []; //used to store entries
for(var hospital of hospitals1.filter(d => !(d.Medicaid == 0 && d.Medicare == 0) && d.Medicare != null)) //loop through valid hospitals
{
var new_entry = {}; //create new entry
new_entry["name"] = hospital.name; //add name
new_entry["entity_id"] = '' + hospital.entity_id; //add entity id as string
new_entry["type"] = "Medicare"; //add type
new_entry["value"] = hospital.Medicare; //add value for that type
stacked_data.push(new_entry); //add new entry to array

new_entry = {}; //empty the entry and add data again for next type
new_entry["name"] = hospital.name;
new_entry["entity_id"] = '' + hospital.entity_id;
new_entry["type"] = "Medicaid";
new_entry["value"] = hospital.Medicaid;
stacked_data.push(new_entry);
new_entry = {};
new_entry["name"] = hospital.name;
new_entry["entity_id"] = '' + hospital.entity_id;
new_entry["type"] = "OtherPublic";
new_entry["value"] = hospital.OtherPublic;
stacked_data.push(new_entry);
new_entry = {};
new_entry["name"] = hospital.name;
new_entry["entity_id"] = '' + hospital.entity_id;
new_entry["type"] = "PrivateInsurance";
new_entry["value"] = hospital.PrivateInsurance;
stacked_data.push(new_entry);
new_entry = {};
new_entry["name"] = hospital.name;
new_entry["entity_id"] = '' + hospital.entity_id;
new_entry["type"] = "PrivatePay";
new_entry["value"] = hospital.PrivatePay;
stacked_data.push(new_entry);

new_entry = {};
new_entry["name"] = hospital.name;
new_entry["entity_id"] = '' + hospital.entity_id;
new_entry["type"] = "CharityCare";
new_entry["value"] = hospital.CharityCare;
stacked_data.push(new_entry);
}
return stacked_data; //return array of new data
}
Insert cell
medicare_sorted = hospitals1.filter(d => !(d.Medicaid == 0 && d.Medicare == 0) && d.Medicare != null).toSorted((a,b) => b.Medicare - a.Medicare);
Insert cell
id_order = {
var id_order = new Array();
medicare_sorted.map(d => id_order.push('' + d.entity_id));
return id_order;
}
Insert cell
stacked_bars = {
var stacked_bars = Plot.plot({
marginBottom: 60, //add margin to bottom
height: 500, //set height
width: width, //use observables default width
x: {tickRotate: -90, tickFormat: "", type: "band", domain: id_order}, // rotate x labels
y: {domain: [0.0, 1.0]},
color: {legend: true, type: "categorical"}, // use categorical colors and include legend
marks: [ // use entity id for x, value for y, type for fill, provided order for stacking, included tooltip
Plot.barY(stacked_data, Plot.groupX({y: "sum"}, {x: "entity_id", y: "value", fill: "type", offset: "normalize", title: "entity_id", sort: null,
order: ["Medicare", "Medicaid", "OtherPublic", "PrivateInsurance", "PrivatePay", "CharityCare"]})),
]
});
return stacked_bars; //return vis
}
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