日本鳥類目録分類図の可視化

1.日本鳥類目録分類図

データの可視化(視覚化)をして見たいと思います。データの可視化はグラフや電子地図上にデータをマッピングしたりして分かりやすくすることです。 これを「データビジュアライゼーション」と言うそうです。特に今回は、題材として階層構造化(ツリー構造)されたデータを可視化ツールとして有名な JavascriptライブラリであるD3.jsを利用して見ました。まず、見える化の第一弾としての題材は鳥類目録の作成をします。

題材における可視化のヒントは、
のサイトで公開されているものが非常に興味深く、参考とさせて頂きました。同じことをやって見たいと思い、データの収集と階層構造 データの作成に取り組みましたので、 その作成手順等を紹介致します。

2.データ作成手順

まずは、鳥類目録の可視化をするために「鳥類目録 第 7 版」をダウンロードします。

    1. 下記のサイトより、日本鳥類目録 第 7 版リスト(mokuroku7.xls)をダウンロード
    (資料提供元 : NPO 法人 バードリサーチ)
    データダウンロード先:http://www.bird-research.jp/1_shiryo/7ed/

    2.ダウンロードしたExcelファイルを開き、目名、科名、種名のみを残し、
        他の列(A列、E列)は削除します。
    3.目名、科名、種名を残した状態で列(A列、B列)を挿入で追加して、
        A列:日本鳥類目録、B列:鳥類を追加します。
    4.階層構造にして、目名と科名の同じものをそれぞれ先頭行のみとして削除します。
    5.階層構造の表ができたら、A列の最終行にEOFの文字列を追加します。
    6.ベースの表ができたので名前を付けて保存するので、任意のブック名で
        一旦、保存します。
    7.続けて、JSON形式に変換(JSON形式ファイルを自動生成)するため、名前を付けて保存で、
        CSV形式(カンマ区切り)で保存します。

CSVファイル名は、「birds.csv」としておいて下さい。(自分で判別できれば、実際は何でも良いです。) ここまでの手順で、データの下ごしらえができました。

    8.階層構造CSVtoJSONコンバータ.xlsmを開き変換ボタンをクリックしてbirds.csvを読み込み変換します。
        ※階層構造CSVtoJSONコンバータにつきましては、こちらを参照願います。

        この操作でコンバータにて階層構造のJSONファイル(birds.json)が出力されます。

3.データの可視化

「苔の絶滅危惧種を R + d3.js で可視化してみた 」 D3.js の radial layout サンプルソースと「D3.js の公式サイト」にある Collapsible Tree d3.V3 版 のサンプルソースから描画領域などの数値を出力結果を見ながら調整して行います。D3.js の最 新版は D3.js V4 版ですが、良く理解していないので、 D3.js V3 版のサンプルを利用させて頂きました。

DEMO

d3sample01.html内のJSONファイル名を変更する場合は、68行を修正して下さい。
68
d3.json("./data/birds.json", function(error, root) {
d3sample01.html [radial layout]
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!doctype html>
<html lang="ja">
<head>
  <title>鳥類目録第7版</title>
  <meta http-equiv="Content-Type" content="text/html; charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta http-equiv="Content-Script-Type" content="text/javascript">
  <meta http-equiv="Content-Style-Type"  content="text/css">
  <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
  <style type="text/css">
    .node circle {
      fill: #ffffff;
      stroke: blue;
      stroke-width: 0.5px;
    }
    .node {
      font: 10px sans-serif;
    }
    .link {
      fill: none;
      stroke: #ccc;
      stroke-width: 1.5px;
    }
    text {
      stroke-width: 0.5px;
    }
    .EX {
      fill: #FF0000;
      stroke: #FF0000;
      stroke-width: 1px;
    }
    .CR_EN {
      fill: #e25f1a;
      stroke: #e25f1a;
    }
    .VU {
      fill: #ffc06b;
      stroke: #ffc06b;
    }
    .NT {
      fill: #168916;
      stroke: #168916;
    }
    .DD {
      fill: #4c4ca7;
      stroke: #4c4ca7;
    }
  </style>
</head>
<body>
<script type="text/javascript">
// ***** 画面全体サイズ *****
  var diameter = 2400;
   
  var tree = d3.layout.tree()
      .size([360, diameter / 2 - 200])
      .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
   
  var diagonal = d3.svg.diagonal.radial()
      .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
   
  var svg = d3.select("body").append("svg")
      .attr("width", diameter)
      .attr("height", diameter)
      .append("g")
      .attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
   
  d3.json("./data/birds.json", function(error, root) {
    var nodes = tree.nodes(root),
        links = tree.links(nodes);
   
    var link = svg.selectAll(".link")
        .data(links)
        .enter().append("path")
        .attr("class", "link")
        .attr("d", diagonal);
   
    var node = svg.selectAll(".node")
        .data(nodes)
      .enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
   
    node.append("circle")
        .attr("r", 4.5);
   
    node.append("text")
        .attr("dy", ".31em")
        .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
        .attr("transform", function(d) { return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)"; })
        .attr("class", function(d) { return d.rank; })
        .text(function(d) { return d.name; });
  });
   
  d3.select(self.frameElement).style("height", diameter - 150 + "px");
     
</script>
</body>
</html>

DEMO

d3sample02.html内のJSONファイル名を変更する場合は、51行を修正して下さい。
51
d3.json("./data/birds.json", function(error, flare) {
d3sample02.html [Collapsible Tree]
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<!doctype html>
<html lang="ja">
<head>
  <title>鳥類目録第7版</title>
  <meta http-equiv="Content-Type" content="text/html; charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta http-equiv="Content-Script-Type" content="text/javascript">
  <meta http-equiv="Content-Style-Type"  content="text/css">
  <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
  <style type="text/css">
.node {
  cursor: pointer;
}
.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 1.2px;
}
.node text {
  font: 9px Meiryo UI;
}
.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 1.2px;
}
</style>
<body>
<script>
 
var margin = {top: 20, right: 120, bottom: 20, left: 120},
    width = 1000 - margin.right - margin.left,
    height = 7000 - margin.top - margin.bottom;
 
var i = 0,
    duration = 750,
    root;
 
var tree = d3.layout.tree()
    .size([height, width]);
 
var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });
 
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
d3.json("./data/birds.json", function(error, flare) {
  if (error) throw error;
 
  root = flare;
  root.x0 = height / 2;
  root.y0 = 0;
 
  function collapse(d) {
    if (d.children) {
      d._children = d.children;
      d._children.forEach(collapse);
      d.children = null;
    }
  }
 
  root.children.forEach(collapse);
  update(root);
});
 
d3.select(self.frameElement).style("height", "5000px");
 
function update(source) {
 
  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);
 
  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });
 
  // Update the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });
 
  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
      .on("click", click);
 
  nodeEnter.append("circle")
      .attr("r", 1e-6)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
 
  nodeEnter.append("text")
      .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
      .text(function(d) { return d.name; })
      .style("fill-opacity", 1e-6);
 
  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
 
  nodeUpdate.select("circle")
      .attr("r", 4.5)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
 
  nodeUpdate.select("text")
      .style("fill-opacity", 1);
 
  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
      .remove();
 
  nodeExit.select("circle")
      .attr("r", 1e-6);
 
  nodeExit.select("text")
      .style("fill-opacity", 1e-6);
 
  // Update the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });
 
  // Enter any new links at the parent's previous position.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", function(d) {
        var o = {x: source.x0, y: source.y0};
        return diagonal({source: o, target: o});
      });
 
  // Transition links to their new position.
  link.transition()
      .duration(duration)
      .attr("d", diagonal);
 
  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
      .duration(duration)
      .attr("d", function(d) {
        var o = {x: source.x, y: source.y};
        return diagonal({source: o, target: o});
      })
      .remove();
 
  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    d.x0 = d.x;
    d.y0 = d.y;
  });
}
 
// Toggle children on click.
function click(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
  update(d);
}
</script>
</body>
</html>
birds.json
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
{
    "name":"鳥類",
    "children":[{
      "name":"キジ目",
      "children":[{
        "name":"キジ科",
        "children":[{
          "name":"エゾライチョウ",
          "rank":""
      },{
          "name":"ライチョウ",
          "rank":""
      },{
          "name":"ウズラ",
          "rank":""
      },{
          "name":"ヤマドリ",
          "rank":""
      },{
          "name":"キジ",
          "rank":""
      }]
    }]
  },{
      "name":"カモ目",
      "children":[{
        "name":"カモ科",
        "children":[{
          "name":"リュウキュウガモ",
          "rank":""
      },{
          "name":"サカツラガン",
          "rank":""
      },{
          "name":"ヒシクイ",
          "rank":""
      },{
 
 
             ~ 中略 ~
 
 
          "name":"マミジロキビタキ",
          "rank":""
      },{
          "name":"キビタキ",
          "rank":""
      },{
          "name":"ムギマキ",
          "rank":""
      },{
          "name":"オジロビタキ",
          "rank":""
      },{
          "name":"オオルリ",
          "rank":""
      },{
          "name":"ロクショウヒタキ",
          "rank":""
      },{
          "name":"チャバラオオルリ",
          "rank":""
      }]
    },{
 
             ~ 中略 ~
 
      },{
          "name":"ゴマフスズメ",
          "rank":""
      },{
          "name":"ウタスズメ",
          "rank":""
      },{
          "name":"ミヤマシトド",
          "rank":""
      },{
          "name":"キガシラシトド",
          "rank":""
      },{
        "name":"サバンナシトド",
        "rank":""
        }]
      }]
    }]
}

4.出力結果

d3sample02.html [radial layout]とd3sample02.html [Collapsible Tree]のそれぞれの実行結果画面です。 尚、D3.jsはPCのローカル環境では動作しませんので、動作確認する場合は必ずWebサーバにアップして行って下さい。

5.ダウンロード

この記事で紹介したサンプルの日本鳥類目録分類図(ソースコード、JSONファイル、出力結果ハードコピー)を配布致します。下記からダウンロードして下さい。

ダウンロード

■関連記事
・階層構造JSONファイルの作成
・日本哺乳類目録分類図の可視化
・日本海産魚類目録分類図の可視化
・鳥類、哺乳類、魚類目録分類図

コメント

このブログの人気の投稿

Excelアドインで日本語形態素解析

階層構造JSONファイルの作成

キーボードのキーコードの一覧表