Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
scatter()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const margin = { top: 20, right: -10, bottom: 40, left: 130 }; // 下の余白を広げる
const width = 800 - margin.left - margin.right;
const height = 300 - margin.top - margin.bottom;

// SVG要素の作成
const svg = d3
.create("svg")
.attr("viewBox", [
0,
0,
width + margin.left + margin.right,
height + margin.top + margin.bottom
]);

const g = svg
.append("g")
.selectAll("g")
.data(areaNames)
.join("g")
.attr("transform", (d, i) => `translate(300, ${20 + i * 30})`);

g.append("text")
.attr("x", 20)
.attr("dy", 5)
.text((d) => d);

g.append("circle").attr("r", 10).attr("fill", colorScale);

return svg.node();
}
Insert cell
Insert cell
translationSankeyChart(translations)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
createBarChart()
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function scatter() {
const margin = { top: 50, right: -10, bottom: 40, left: 130 }; // 下の余白を広げる
const width = 800 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;

// SVG要素の作成
const svg = d3
.create("svg")
.attr("viewBox", [
0,
0,
width + margin.left + margin.right,
height + margin.top + margin.bottom
]);

// スケール関数
const xScale = d3
.scaleLog()
.domain([200000, d3.max(dataset, (d) => d.population)])
.range([margin.left, width - margin.right]);

const yScale = d3
.scaleLog()
.domain([1, d3.max(dataset, (d) => d.number)])

.range([height - margin.bottom - 30, margin.top]);

const rScale = d3.scaleSqrt().domain([0, 20]).range([0, 40]);

// 横線グリッド
svg
.append("g")
.selectAll("line")
.data(yScale.ticks(3))
.join("line")
//.attr("x1", xScale(0))
.attr("x1", margin.left) // グリッドの始点を左の余白に合わせる
.attr("x2", xScale(d3.max(dataset, (d) => d.population)))
.attr("y1", (d) => yScale(d))
.attr("y2", (d) => yScale(d))
.attr("stroke", "#ccc");

svg
.append("g")
.selectAll("line")
.data(xScale.ticks(3))
.join("line")
.attr("x1", (d) => xScale(d))
.attr("x2", (d) => xScale(d))
.attr("y1", yScale(1))
.attr("y2", yScale(d3.max(dataset, (d) => d.number)))
.attr("stroke", "#ccc");

// ドットとテキスト
const dots = svg
.append("g")
.selectAll("g")
.data(dataset)
.join("g")
.attr(
"transform",
(d) => `translate(${xScale(d.population)}, ${yScale(d.number)})`
);

dots
.append("circle")
.attr("r", 10)
.attr("fill", "#4A84B8")
.attr("opacity", 0.5);

dots
.append("text")
.text((d) => d.language) // 表示したいプロパティに変更
.attr("text-anchor", "middle")
.attr("y", -20)
.attr("dy", "0.25em")
.style("font-size", "10px")
.attr("transform", (d) =>
d.number === d3.min(dataset, (d) => d.number) ? "rotate(-15)" : ""
) // 条件に基づいてラベルを回転
.style("pointer-events", "none");

// ドットの重なりを確認して、重なっている場合はラベルを省略
dots.each((d, i, nodes) => {
const currentDot = d3.select(nodes[i]);
const x1 = +currentDot.attr("transform").split(",")[0].slice(10);
const y1 = +currentDot.attr("transform").split(",")[1].slice(0, -1);

// 他のドットと比較
dots.each((dd, ii, nn) => {
if (i !== ii) {
const x2 = +d3.select(nn[ii]).attr("transform").split(",")[0].slice(10);
const y2 = +d3
.select(nn[ii])
.attr("transform")
.split(",")[1]
.slice(0, -1);

// 一定の距離以下にドットが重なっている場合はラベルを省略
if (Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) < 20) {
currentDot.select("text").style("visibility", "hidden");
}
}
});
});

tooltip
.append("rect")
.attr("fill", "white")
.attr("stroke", "#DDDDDD")
.attr("width", 145)
.attr("height", 105)
.attr("opacity", 0.8);

// ドットにマウスが乗ったらツールチップを表示
dots

.on("mouseover", function (e, d, i) {
tooltip
.html(
`<div>${d.language}<br>人口:${d.population}<br>受賞数:${d.number}</div>`
)
.style("visibility", "visible");

d3.select(this).attr("opacity", 1);
})
.on("mousemove", function (e) {
// ツールチップの横幅を取得
var tooltipWidth = tooltip.node().offsetWidth;

// マウスのX座標によって条件分岐
var tooltipX =
e.pageX < window.innerWidth / 2
? e.pageX + 10
: e.pageX - tooltipWidth - 10;

// ツールチップをマウスの位置に移動
tooltip
.style("top", e.pageY + 10 + "px")
.style("left", tooltipX + "px")
.style("width", "200px");
})
.on("mouseout", function () {
tooltip.html(``).style("visibility", "hidden");
d3.select(this).transition();
});

// 軸関数
const xAxis = d3.axisBottom().scale(xScale);
const yAxis = d3.axisLeft().scale(yScale);

// 軸表示
svg
.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(xAxis);

svg.append("g").attr("transform", `translate(${margin.left},0)`).call(yAxis);

// テキスト
svg
.append("text")
.attr("text-anchor", "middle")
// .attr("transform", `translate(${width / 2},${height - 10})`) // 位置を調整
.attr("x", width / 2)
.attr("y", height)
.text("話者数");

svg
.append("text")
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
.attr("y", margin.left / 4) // 位置を調整
.attr("x", -height / 2)
.text("受賞数");

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
translationSankeyChart = (data, { source } = {}) => {
const links = source ? data.filter((d) => d.source === source) : data;
const height = links.length * (source ? 20 : 3);

return SankeyChart(
{
links
},
{
nodeGroup: (d) => d.id.split("_").at(-1), // 地域名のみに変換
nodeGroups: areaNames, // 配色を固定するために地域名の配列を指定
nodeAlign: d3.sankeyJustify, // e.g., d3.sankeyJustify; set by input above,
nodeLabel: (d) => d.id.split("_").at(-2), // 言語名のみに変換
nodePadding: 1,
nodeStroke: "#fff",
nodeWidth: 50,
colors: areaColors, // 配色
nodeTitle: (d) => `${d.id.split("_").at(-2)}\n${format(d.value)}`, // given d in (computed) nodes, hover text
linkTitle: (d) =>
`${d.source.id.split("_").at(-2)} から ${d.target.id
.split("_")
.at(-2)} へ\n${format(d.value)}`, // given d in (computed) links
width,
height
}
);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function createBarChart() {
// グラフの寸法を設定
const margin = { top: 50, right: 50, bottom: 100, left: 100 };
const width = 700 - margin.left - margin.right;
const height = 700 - margin.top - margin.bottom;

// SVG を作成
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

// ツールチップ要素を作成
const tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "10px");

// 各地域ごとに横棒グラフを描画
const regions = Array.from(new Set(datasetWithArea.map((d) => d.area)));

const numChartsPerRow = 1; // 1行あたりの横棒グラフの数

const paddingFactor = 1;

regions.forEach((region, i) => {
const row = Math.floor(i / numChartsPerRow);
const col = i % numChartsPerRow;

const chartWidth = width / numChartsPerRow;
const chartHeight = height / Math.ceil(regions.length / numChartsPerRow);
const barWidth = chartWidth / 2; // 棒の幅を設定

const regionData = datasetWithArea.filter((d) => d.area === region);

// 各言語の合計数を計算
const totalLanguages = regionData.length;
const languageCounts = d3.rollup(
regionData,
(v) => v.length / totalLanguages, // 各言語の割合を計算
(d) => d.original
);

const languageCountsArray = Array.from(
languageCounts,
([original, count]) => ({ original, count })
);
languageCountsArray.sort((a, b) => d3.descending(a.count, b.count));

// 積み上げ横棒グラフ用のデータを作成
let cumulative = 0;
for (const d of languageCountsArray) {
d.start = cumulative;
cumulative += d.count;
d.end = cumulative;
}

const yScale = d3
.scaleBand()
.domain(languageCountsArray.map((d) => d.original))
.range([0, chartHeight])
.padding(0.1);

const xScale = d3.scaleLinear().domain([0, 1]).range([0, chartWidth]);

const chartGroup = svg
.append("g")
.attr(
"transform",
`translate(${col * chartWidth * paddingFactor},${
row * chartHeight * paddingFactor
})`
);

// 地域名を表示
chartGroup
.append("circle")
.attr("cx", margin.left - 80)
.attr("cy", margin.top - 16)
.attr("r", 5) // 円の半径
.attr("fill", (d) => colorScale(region)); // 各地域に対応する色を設定

chartGroup
.append("text")
.attr("x", margin.left - 70) // テキストのx座標をmargin.leftに設定
.attr("y", margin.top - 13) // 上部に配置するため、y座標をmargin.topに設定
.attr("text-anchor", "start")
.attr("fill", "black")
.text(region)
.attr("font-size", "10px");

// 積み上げ横棒グラフを描画
chartGroup
.selectAll("rect")
.data(languageCountsArray)
.enter()
.append("rect")
.attr("x", (d) => xScale(d.start))
.attr("width", (d) => xScale(d.end) - xScale(d.start))

.attr("height", 20) // すべての帯の高さを20に設定する

.attr("fill", (d) => colorScale2(d.original))
// ツールチップを表示するイベントを追加
.on("mouseover", function (event, d) {
tooltip
.style("visibility", "visible")
.html(
`<div>${d.original}<br>割合:${d3.format(".1%")(d.count)}</div>`
);
})

.on("mousemove", function (event) {
var tooltipWidth = tooltip.node().offsetWidth;
// マウスのX座標によって条件分岐
var tooltipX =
event.pageX < window.innerWidth / 2
? event.pageX + 10
: event.pageX - tooltipWidth - 10;
// ツールチップをマウスの位置に移動
tooltip
.style("top", event.pageY + 10 + "px")
.style("left", tooltipX + "px")
.style("width", "200px");
})

.on("mouseout", function () {
tooltip.style("visibility", "hidden");
});

// 棒の上に数値を表示
chartGroup
.selectAll(".label")
.data(languageCountsArray)
.enter()
.append("text")
.attr("class", "label")
.attr("x", (d) => xScale(d.start))
.attr("dy", "1em")
.attr("dx", 5)
.attr("text-anchor", "start")
.text((d) => {
if (xScale(d.end) - xScale(d.start) > 60) {
return d.original;
} else {
return "";
}
})
.attr("font-size", "8px")
.attr("font-family", "sans-serif")
// .attr("font-size", 10)

.attr("font-weight", 600)
.attr("stroke", "#fff")
.attr("stroke-width", 2)
.attr("paint-order", "stroke fill");
});

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