Public
Edited
Apr 3, 2023
2 forks
Insert cell
Insert cell
proportionalSymbols = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
//This creates my svg "canvas" for my page. The width and height of the page is defined below as variables.

svg.append("path")
.datum(topojson.feature(basepolygons_states, basepolygons_states.objects.States))
.attr("fill", "#ccc")
.attr("d", path_basemap);
// The datum is the topojson of my basemap, which is the US states called basepolygons_states. The object within that is called States.
// The gray color will fill my polygons since this is serving as just a basemap. The color is #ccc and fills in the polygon.
// The path_basemap is the projection path to display the map as the Albers USA projection.
svg.append("path")
.datum(topojson.mesh(basepolygons_states, basepolygons_states.objects.States, (a, b) => a !== b))
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("d", path_basemap);
// The boarders of my polygons of the states are defined as white and shown as only one line for each polygon
// The mesh function turns our topojson base polygons of the states into our boarder lines.

const legend = svg.append("g")
.attr("fill", "#777")
.attr("transform", "translate(825,400)")
.attr("text-anchor", "middle")
.style("font", "10px sans-serif")
.selectAll("g")
.data([9783, d3.max([...data.values()])])
.join("g");
// This function creates the legend element. I can change where the legend is displayed on my canvas by changing the translate(#,#) portion of the legend. For this case, I have the legend displayed on the bottom left corner in the map.
// The size of the circles displayed on the legend are shown as a manually entered value and the maximum value of the proportional symbols. In this case I took the 1/4 of the maximum value (9783) and the max value of the number of providers in a city. This is done using the code .data([9783, d3.max([...data.values()])])

legend.append("circle")
.attr("fill", "none")
.attr("stroke", "#ccc")
.attr("cy", d => -radius(d))
.attr("r", radius);
// This takes the legend element and adds the circles to the legend to be represented as 1/4 of the maximum value and the max value of the number of providers in a city.
legend.append("text")
.attr("y", d => -2 * radius(d))
.attr("dy", "1.3em")
.text(format);


// This is how the point symbols are added to the map.
svg.append("g")
.attr("fill", "#8856a7")
// This is the color I want to fill my points with (that will be shown as the proportional symbol).
.attr("fill-opacity", 0.5)
// Fill transparency for my points. It is currently at 50%
.attr("stroke", "#252525")
// This is the color of the outline for the point symbol.
.attr("stroke-width", 0.5)
// This is the thickness of the point symbol outline.
.selectAll("circle")
// The point symbols will be represented as a circle.
.data(points.features
// This gathers the features from my data calls points. It goes through each shape and takes the ID (That is CtySt) and returns the value and assigns it to the point.
.map(d => (d.value = data.get(uppercase(d.properties.CtySt)), d))
.sort((a, b) => b.value - a.value))
// The sort function orders the circles by size and then the larger circles are displayed in the back so that the small circles, if they overlap with the larger circles can be seen.
.join("circle")
.attr("transform", d => `translate(${path_points.centroid(d)})`)
//This finds the centroid of the circle and shows the circle right in the center of point.
.attr("r", d => radius(data.get(uppercase(d.properties.CtySt))))
// Once the value of the number of providers has been returned, it will assign the point as radius size depending upon the value and the size of canvas. It assigns it an attribute "r" which is the radius of the circle
.append("title")
.text(d => `${uppercase(d.properties.CtySt)} : ${format(d.value)}`);
// When the reader hovers over the point (city,state), the ID of the point and the value of the number of providers of that point is displayed.


return svg.node();
}
Insert cell
height = 610
Insert cell
Insert cell
width = 975
Insert cell
Insert cell
path_points = d3.geoPath().projection(projection)
Insert cell
Insert cell
path_basemap = d3.geoPath().projection(projection)
Insert cell
Insert cell
projection = d3.geoAlbers()
Insert cell
Insert cell
format = d3.format(",.0f")
Insert cell
Insert cell
d3.max([...data.values()])
Insert cell
Insert cell
radius(39133)
Insert cell
Insert cell
radius(186)
Insert cell
Insert cell
//proportional symbols
radius = d3.scaleSqrt([0, d3.max([...data.values()])], [0, 25])
Insert cell
Insert cell
data.get("SOUTH JORDAN")
Insert cell
Insert cell
data = Object.assign(new Map(csv_data))
Insert cell
csv_data = d3.csvParse(await FileAttachment("Cities count prov_raw.csv").text(), ({cty, Count}) => [cty, +Count])
Insert cell
Insert cell
//uppercase = function(d){
//return d.toUpperCase()
//}
Insert cell
//import the point data (geojson)
points = FileAttachment("Cities_CtySt (1) (1).json").json()
Insert cell
IApoints = points.features.filter(d => d.properties.STATE === "IA");
Insert cell
Insert cell
basepolygons_states = FileAttachment("IA_state.json").json()
Insert cell
Insert cell
simple = require("simple-statistics@7.0.7/dist/simple-statistics.min.js")
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3@5")
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