Published
Edited
Mar 31, 2021
Insert cell
md`# Project 3: D3`
Insert cell
d3 = require.alias({
"d3-array": "d3@6",
"d3-axis": "d3@6",
"d3-dispatch": "d3@6",
"d3-drag": "d3@6",
"d3-ease": "d3@6",
"d3-scale": "d3@6",
"d3-selection": "d3@6",
"d3-transition": "d3@6"
})("d3@6", "d3-simple-slider@1")
Insert cell
airbnb_data = FileAttachment("Airbnb_Host_Housing.csv").csv()
Insert cell
airbnb_data
Insert cell
times[1]
Insert cell
times = Array("2018", "2019", "2020", "2021")
Insert cell
time
Insert cell
viewof time = {

const slider = d3.sliderBottom()
.min(2018)
.max(2021)
.width(300)
.ticks(3)
.tickFormat(d3.format("1"))
.on("onchange", () => svg.dispatch("input"));

const svg = d3.create("svg")
.attr("viewBox", [-20, -20, 340, 60])
.attr("width", 340)
.attr("height", 60)
.call(slider);

return Object.defineProperty(
svg.node(),
"value",
{get: () => slider.value()}
);
}
Insert cell
w = {
let by_year = d3.group(airbnb_data, d => d.year);
var yeary = time;
return by_year.get(yeary+"");
}
Insert cell
chart_param = ({
width: width,
height: 500,
margin: {
top: 10,
right: 10,
bottom: 10,
left: 10,
center: 150
}
})
Insert cell
//copy to preserve the data
//nodes = data.map(d => Object.create(d))
Insert cell
data_sorted = w.sort(function (a, b) {
return b.calculated_host_listings_count - a.calculated_host_listings_count;
});
Insert cell
//data.map(data => ({x: x(Math.min(Math.max(d3.randomNormal(0.5, 0.15)(), 0), 1)),
// y: y(Math.min(Math.max(d3.randomNormal(0.5, 0.15)(), 0), 1))}))
nodes = {
for (var s = 0; s < data_sorted.length; s++) {
data_sorted[s].x = x(Math.min(Math.max(d3.randomNormal(0.5, 0.15)(), 0), 1))
data_sorted[s].y = y(Math.min(Math.max(d3.randomNormal(0.5, 0.15)(), 0), 1))
data_sorted[s].r = r(data_sorted[s].revenue)
if (s < 10) {
data_sorted[s].group = s + 1
} else {
data_sorted[s].group = 11
}
}
return data_sorted
}
Insert cell
viewof replay = html`<button>Replay`
Insert cell
chart_force = {
replay;
const svg = d3.select(DOM.svg(chart_param.width, chart_param.height)),
nodes1 = nodes.map(d => Object.create(d));
const sim = d3.forceSimulation(nodes1)
.force("x", d3.forceX(x(0.5)))
.force("y", d3.forceY(y(0.5)))
.force("collide", d3.forceCollide().radius(d => d.r + 1));
const node = draw_nodes(svg, nodes1);
node.transition()
.delay((d, i) => Math.random() * 500)
.duration(750)
.attrTween("r", d => {
const i = d3.interpolate(0, d.r);
return t => d.r = i(t);
});
sim.on("tick", () => {
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
return svg.node()
}
Insert cell
color = d3.scaleOrdinal(d3.range(11),d3.schemeSpectral[11])
Insert cell
draw_nodes = (svg, node_data) => {
const node = svg.selectAll(".node")
.data(node_data).enter()
.append("circle")
.classed("node", true)
.attr("cx", d => d.x)
.attr("cy", d => d.y);
// .attr("r", d => d.r);
return node;
}
Insert cell
x = d3.scaleLinear()
.domain([0.1, 1])
.range([chart_param.margin.left, chart_param.width - chart_param.margin.right]);
Insert cell
y = d3.scaleLinear()
.domain([0, 1])
.range([chart_param.height - chart_param.margin.bottom, chart_param.margin.top]);
Insert cell
w_range = d3.scaleSequential(w).range()
Insert cell
r = d3.scaleLinear()
.domain(w_range)
.range([0, 1]);
Insert cell
// x, y and r taken from https://observablehq.com/@ben-tanen/a-tutorial-to-using-d3-force-from-someone-who-just-learned-ho
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