NISHIO Hirokazu[日本語][English]

Polis2024-08-20

2024-08-19 https://pol.is/4jbpxizvxf https://pol.is/api/v3/participationInit?conversation_id=4jbpxizvxf&pid=mypid&lang=acceptLang このAPIが返すデータをinitDataとして js

pca = JSON.parse(initData["pca"])

xs = pca["base-clusters"]["x"]
ys = pca["base-clusters"]["y"]
ids = pca["base-clusters"]["id"]

// id->(x,y)の対応を作成
const idToCoordinates = {};

ids.forEach((id, index) => {
    idToCoordinates[id] = {
        x: xs[index],
        y: ys[index]
    };
});


// pca["group-clusters"]からクラスタ情報を抽出
const groupClusters = pca["group-clusters"];

// クラスタごとのデータを作成
data = []
const clusterData = groupClusters.forEach((cluster, index) => {
  cluster.members.forEach((id)=>{
    data.push({
      cluster: index, 
      ...idToCoordinates[id]
    });
  });
});

// SVGの設定
const width = 600;
const height = 400;
const margin = {top: 20, right: 20, bottom: 30, left: 40};

const svg = d3.select("#scatter-plot")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);

// スケールの設定
const xScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.x))
.range([0, width]);

const yScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.y))
.range([height, 0]);

// 軸の追加
svg.append("g")
  .attr("transform", `translate(0,${height})`)
  .call(d3.axisBottom(xScale));

svg.append("g")
  .call(d3.axisLeft(yScale));



// カラースケールの設定
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);

// 散布図のプロット
svg.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", d => xScale(d.x))
  .attr("cy", d => yScale(d.y))
  .attr("r", 5)
  .style("fill", d => colorScale(d.cluster));

// ラベルの追加
svg.selectAll("text")
  .data(data)
  .enter()
  .append("text")
  .attr("x", d => xScale(d.x) + 10)
  .attr("y", d => yScale(d.y))
  .text(d => d.label)
  .style("font-size", "12px");


// Convex Hull生成関数
console.log("hello");

// クラスターごとにデータをグループ化
const clusters = d3.group(data, d => d.cluster);

// Convex Hullの描画
const hull = d3.polygonHull;
clusters.forEach((points, cluster) => {
  const hullPoints = hull(points.map(d => [xScale(d.x), yScale(d.y)]));
  if (hullPoints) {
    svg.append("path")
      .datum(hullPoints)
      .attr("d", d => `M${d.join("L")}Z`)
      .attr("fill", colorScale(cluster))
      .attr("fill-opacity", 0.2)
      .attr("stroke", colorScale(cluster))
      .attr("stroke-width", 2);
  }
});

image https://codepen.io/nishiohirokazu/pen/WNqMJxw?editors=0010

image 上下が逆なだけで同じクラスタ形状にはできてる

d3.polygonHull


(C)NISHIO Hirokazu / Converted from Markdown (ja)
Source: [GitHub] / [Scrapbox]