Published
Edited
Nov 23, 2020
1 star
Insert cell
Insert cell
tree_layout(d)
Insert cell
function tree_layout(tree_data) {
const root = d3.hierarchy(tree_data);
const layout = d3.tree()
// .size([chart.chartHeight(), chart.chartWidth()])
.nodeSize([100, 200])
.separation((a, b) => 1);
layout(root);
const xExtent = d3.extent(root.descendants(), node => node.x);
const yExtent = d3.extent(root.descendants(), node => node.y);
const margin = { top: 30, right: 30, bottom: 30, left: 30 };
const chartSize = {
width: yExtent[1] + margin.left + margin.right,
height: xExtent[1] - xExtent[0] + margin.top + margin.bottom
};
const chart = prepareChart(chartSize, margin);
chart.svg.append("style").text(treeStyle.innerHTML);
const x = d3.scaleLinear()
.range([0, chart.chartWidth()])
.domain(yExtent);
const y = d3.scaleLinear()
.range([0, chart.chartHeight()])
.domain(xExtent);
chart.chartArea.selectAll("path.edge")
.data(root.links())
.join("path")
.classed("edge", true)
.attr("d", d => `M ${x(d.source.y)},${y(d.source.x)} Q ${x(d.source.y)},${y(d.target.x)} ${x((2*d.source.y + d.target.y)/3)},${y(d.target.x)} L ${x(d.target.y)},${y(d.target.x)}`);
chart.chartArea.selectAll("text.edge-label")
.data(root.links())
.join("text")
.classed("edge-label", true)
.attr("x", d => x((2 * d.source.y + 3 * d.target.y) / 5))
.attr("y", d => y(d.target.x) - 10)
.text(d => d.target.data.label);
chart.chartArea.selectAll("text.edge-probability")
.data(root.links().filter(d => d.source.data.type === "chance"))
.join("text")
.classed("edge-probability", true)
.attr("x", d => x((2 * d.source.y + 3 * d.target.y) / 5))
.attr("y", d => y(d.target.x) + 20)
.text(d => d.target.data.probability);

chart.chartArea.selectAll("circle.chance.node")
.data(root.descendants().filter(d => d.data.type === "chance"))
.join("circle")
.classed("chance node", true)
.attr("cx", d => x(d.y))
.attr("cy", d => y(d.x))
.attr("r", 5.64);
chart.chartArea.selectAll("rect.decision.node")
.data(root.descendants().filter(d => d.data.type === "decision"))
.join("rect")
.classed("decision node", true)
.attr("x", d => x(d.y) - 5)
.attr("y", d => y(d.x) - 5)
.attr("width", 10)
.attr("height", 10);
chart.chartArea.selectAll("path.outcome.node")
.data(root.descendants().filter(d => d.data.type === "outcome"))
.join("path")
.classed("outcome node", true)
.attr("d", d => `M ${x(d.y)-7.07},${y(d.x)} L ${x(d.y)+7.07},${y(d.x)-7.07} L ${x(d.y)+7.07},${y(d.x)+7.07} z`);
return chart.svg.node();
}
Insert cell
Insert cell
Insert cell
d = ({
children: [
{
label: "Ballot Party",
type: "decision",
children: [
{
label: "Democrat",
type: "chance",
children: [
{
label: "Straight Ticket",
type: "outcome",
probability: "S_D"
},
{
label: "Split Ticket",
type: "chance",
probability: "(1-S_D)",
children: [
{
label: "Not Defect",
type: "outcome",
probability: "(1-P_D)"
},
{
label: "Defects",
type: "outcome",
probability: "P_D"
}
]
}
]
},
{
label: "Republican",
type: "chance",
children: [
{
label: "Straight Ticket",
type: "outcome",
probability: "S_R"
},
{
label: "Split Ticket",
type: "chance",
probability: "(1-S_R)",
children: [
{
label: "Not Defect",
type: "outcome",
probability: "(1-P_R)"
},
{
label: "Defects",
type: "outcome",
probability: "P_R"
}
]
}
]
}
]
}
]
})
Insert cell
Insert cell
Insert cell
Insert cell
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