LATEST ENTRIES
CATEGORIES
ARCHIVES
SPONSORED LINK
MOBILE
qrcode
LINKS
PROFILE
OTHERS

12
--
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
--
>>
<<
--

Agata's Blog

MATLABやPythonとともにD3.jsを使ってデータ解析とデータビジュアライゼーションに挑戦する某エンジニアのBlog
<< 過去30日間に世界で発生した地震を可視化する | main | 過去30日間に世界で発生した地震を可視化する その2 >>
【D3.js】Chordダイアグラムの作成
0
    JUGEMテーマ:JavaScript

    D3.js には Chordダイアグラム (Chord diagram) を作成するための d3.layout.chord() というメソッドがあるのですが、そもそも Chordダイアグラム自体に馴染みがないというかたが多いのではないでしょうか。そこで、Chordダイアグラムについて簡単に説明したうえで、D3.jsによる作成方法を紹介します。

    Chordダイアグラムは、グループ間の関連性を図示するときによく使われます。例えば、ある集団を「男性/女性」という2つのグループに分けた場合と、「犬好き/猫好き」という2つのグループに分けた場合について考えてみましょう。現実の世のなかには「犬も猫も好き」な人もいれば、「どちらもキライ!」という人もいますが、ここでは簡単のために、みんな犬か猫のどちらか一方が好きだとします。さて、こうするとこの集団のメンバーは、4 種類 (「男性で犬好き」「男性で猫好き」「女性で犬好き」「女性で猫好き」) に分類できることになりますね。具体的に考えるために、この集団は男性12人と女性4人から成り、それぞれ以下のように犬好きと猫好きに分かれているとします。
     
    犬好き 猫好き 合計
    男性 7 5 12
    女性 1 3 4
    合計 8 8

    さて、このようなデータを可視化するときに、Chord ダイアグラムが役立ちます。Chord ダイアグラムを使うと、こういうグループ間の関連性を一目で把握できるようになります。上の表をもとに、実際に作成したChordダイアグラムが下図になります。



    ここでは図の右側、青色とオレンジ色の円弧が「男性/女性」のグループを表しています。また、左側の緑色と赤色の円弧が「犬好き/猫好き」のグループを表しています。そしてそれぞれのグループ間を橋渡ししている赤と緑の帯が、それぞれの関連性 (「男性で犬好き」など) を表現しています。このように、Chordダイアグラムを使うと、先の表にあるような2種類のグループ間の関連や連携が、見事に1枚の図に表現されていることが分かります。

    サンプルページ

    // D3.jsによる基本10色
    var color = d3.scale.category10();
    
    // Chord diagramの元となるデータ
    var matrix = [
        [0, 0, 7, 5],
        [0, 0, 1, 3],
        [7, 1, 0, 0],
        [5, 3, 0, 0]
    ];
    
    // D3.layout.chord()メソッドを使ってChordダイアグラムを作成
    var chord = d3.layout.chord()
        .padding(.05)
        .matrix(matrix);
    
    var width = 600,
        height = 500,
        innerRadius = Math.min(width, height) * 0.4,
        outerRadius = innerRadius * 1.1;
    
    var svg = d3.select("#MyGraph")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
    // Chord diagramを描画
    svg.append("g").selectAll("path")
        .data(chord.groups)
        .enter()
        .append("path")
        .style("fill", function(d){ return color(d.index); })
        .style("stroke", function(d) { return color(d.index); })
        .style("opacity", 0.8)
        .attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
        .on("mouseover", fade(.1)) // マウスをのせた部分を強調表示
        .on("mouseout", fade(0.8)); // マウスを移動すると描画を元に戻す
    
    // 目盛りを描画
    var ticks = svg.append("g").selectAll("g")
        .data(chord.groups)
        .enter()
        .append("g")
        .selectAll("g")
        .data(groupTicks)
        .enter()
        .append("g")
        .attr("transform", function(d) {
          return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
              + "translate(" + outerRadius + ",0)";
        });
    
    ticks.append("line")
        .attr("x1", 1)
        .attr("y1", 0)
        .attr("x2", 5)
        .attr("y2", 0)
        .style("stroke", "#000");
    
    // 目盛りの数字を描画
    ticks.append("text")
        .attr("x", 8)
        .attr("dy", ".35em")
        .attr("transform", function(d) {
            return d.angle > Math.PI ? "rotate(180)translate(-16)" : null;
        })
        .style("text-anchor", function(d) {
            return d.angle > Math.PI ? "end" : null;
        })
        .text(function(d) { return d.label; });
    
    svg.append("g")
        .attr("class", "chord")
        .selectAll("path")
        .data(chord.chords)
        .enter()
        .append("path")
        .attr("d", d3.svg.chord().radius(innerRadius))
        .style("fill", function(d) { return color(d.target.index); })
        .style("opacity", 0.9);
    
    // 描画する目盛りの数字と角度を返す関数
    function groupTicks(d) {
      var k = (d.endAngle - d.startAngle) / d.value;
      return d3.range(0, d.value).map(function(v, i) {
        return {
          angle: v * k + d.startAngle,
          label: i % 5 ? null : v
        };
      });
    }
    
    // mouseover/mouseout 時のSVG要素の透明度を決定する関数
    function fade(opacity) {
      return function(g, i) {
        svg.selectAll(".chord path")
            .filter(function(d) {
                return d.source.index != i && d.target.index != i;
            })
            .transition()
            .style("opacity", opacity);
      };
    }
    



     
    このエントリーをはてなブックマークに追加
    | D3.js | 23:07 | comments(0) | - | - |
    スポンサーリンク