Published
Edited
Jul 14, 2020
Insert cell
md`# Circle packing`
Insert cell
flare = d3.csvParse(await FileAttachment("frequency_with_count.csv").text())
Insert cell
d3=require("d3@5","d3-array@2")
Insert cell
reduceFn = iterable => d3.sum(iterable, d => d["percent"]);
Insert cell
groupingFns = [d => d.cate,d=>d.words]
Insert cell
rollupData = d3.rollup(flare, reduceFn, ...groupingFns);
Insert cell
childrenAccessorFn = ([ key, value ]) => value.size && Array.from(value)
Insert cell
hierarchyData = d3.hierarchy([null, rollupData], childrenAccessorFn)
.sum(([,value]) => value)
.sort((a, b) => b.value - a.value)
Insert cell
pack = () => d3.pack()
.size([800,500])
.padding(1)
(hierarchyData)
Insert cell
pack(hierarchyData)
Insert cell
chart = {
const root = pack(hierarchyData);

const svg = d3.create("svg")
.attr("viewBox", [0, 0, 800, 800])
.style("font", "10px sans-serif")
.attr("text-anchor", "middle");

const shadow = DOM.uid("shadow");

svg.append("filter")
.attr("id", shadow.id)
.append("feDropShadow")
.attr("flood-opacity", 0.3)
.attr("dx", 0)
.attr("dy", 1);

const node = svg.selectAll("g")
.data(d3.nest().key(d => d.height).entries(root.descendants()))
.join("g")
// .attr("filter", shadow)
.selectAll("g")
.data(d => d.values)
.join("g")
.attr("transform", d => `translate(${d.x + 1},${d.y + 1})`);

node.append("circle")
.attr("r", d => d.r)
.attr("fill", d => color(d.height));

const leaf = node.filter(d => !d.children);
leaf.select("circle")
.attr("id", d => (d.leafUid = DOM.uid("leaf")).id);

leaf.append("clipPath")
.attr("id", d => (d.clipUid = DOM.uid("clip")).id)
.append("use")
.attr("xlink:href", d => d.leafUid.href);

leaf.append("text")
.attr("clip-path", d => d.clipUid)
.selectAll("tspan")
.data(d => (d.data[0] + "").split(/\s+/g))
.join("tspan")
.attr("x", 0)
.attr("y", (d, i, nodes) => `${i - nodes.length / 2 + 0.8}em`)
.text(d => d)
.attr('font-size','10px');

node.append("title")
.text(d => `${d.ancestors().map(d => d.data.name).reverse().join("/")}\n${d.value}`);
return svg.node();
}
Insert cell
chart2 = {
const root = pack(hierarchyData);

const svg = d3.select(DOM.svg(1000, 600))
.style("font", "10px sans-serif")
.style("width", "100%")
.style("height", "auto")
.style("overflow", "visible");

svg.append("g")
.attr("fill", "#ccc")
.selectAll("circle")
.data(root.leaves())
.join("circle")
.attr("transform", d => `translate(${d.x},${d.y})`)
.attr("r", d => d.r)
.append("title")
.text(d => `${d.ancestors().map(d => d.data[0]).reverse().join("/")}\n${d.value}`);

svg.append("g")
.attr("pointer-events", "none")
.attr("text-anchor", "middle")
.selectAll("text")
.data(root.leaves().filter(d => d.r > 2))
.join("text")
.attr("transform", d => `translate(${d.x},${d.y}) scale(${d.r / 30})`)
.selectAll("tspan")
.data(d => (d.data[0] + "").split(/\s+/g))
.join("tspan")
.attr("x", 0)
.attr("y", (d, i, nodes) => `${i - nodes.length / 2 + 0.8}em`)
.text(d => d);

return svg.node();
}
Insert cell
color = d3.scaleSequential([8, 0], d3.interpolateMagma)
Insert cell
region_arr=["美国","非洲","印度","西方","日本","欧洲","英国","意大利","巴基斯坦","法国","俄罗斯","韩国","尼日利亚"]
Insert cell
regions=flare.filter(d=>region_arr.includes(d.words))
Insert cell
regions[0]['total_mention']=17485
Insert cell
regions.map(d=>d.total_mention)
Insert cell
lineradial = {
const w = 960;
const h = 960;
const svg = d3.create('svg').attr('viewBox', [0, 0, w, h]);
const data = regions.map(d=>d.total_mention)
data[0]=17485
// データからグループを生成し、それぞれ原点移動・回転する
const g = svg
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('transform', function(d, i) {
return `translate(${w / 2}, ${h / 2}) rotate(${i * 20})`;
});
const linescale=d3.scaleSqrt().domain([0,20000]).range([0,500])
// グループにラインを追加
g.append('line')
.attr('x1', 0)
.attr('y1', 20)
.attr('x2', 0)
.attr('y2', function(d) {
return linescale(d);
})
.attr('stroke-width', 2)
.attr('stroke', 'steelblue');

// グループにラベルを追加
g.append('text')
.attr('x', 0)
.attr('y', function(d) {
return linescale(d) ;
})
.attr('dy', '1em')
.attr('fill', 'orange')
.attr('font-family', 'sans-serif')
.attr('font-size', '10px')
.attr('text-anchor', 'middle')
.text(function(d) {
return d3.format('0d')(d);
});

return svg.node();
}
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