読者です 読者をやめる 読者になる 読者になる

君たちは永遠にそいつらより若い

技術と音楽と日々のこと。

DATA GO JPで公表されている苔の絶滅危惧種を R + d3.js で可視化してみた

D3.js R


Day 24: d3.js Advent Calendar 2013

こんにちは。くてけんです。うかうかしていて、サンフランシスコ時間での投稿になりました。

4,5日前に政府のデータカタログサイトの試行版として、DATA GO JP(http://www.data.go.jp/)がリリースされました。これはナイスタイミング!ということで、このDATA GO JPで公表されているデータを使って、R + d3.js でデータ可視化を行ってみました。

今回の流れ

  1. DATA GO JP から使用するデータセットを選ぶ
  2. R でデータ整形
  3. d3.js でビジュアライゼーション

DATA GO JP から使用するデータセットを選ぶ

こちらからデータセットが検索できますが、まずJSONデータは無いので、CSVをターゲットに検索し、今回扱うデータを決めます。

http://www.data.go.jp/data/dataset?res_format=CSV

そして、今回選んだのは、蘚苔類の絶滅危惧種です。理由は、僕はとても苔が好きだからですね!美しい。かわいい。撫でると気持ちいい♡(ちなみにお気に入りの苔はハイゴケです。)

環境省自然環境局野生生物課 第4次レッドリスト(日本の絶滅のおそれのある野生生物の種のリスト) http://www.data.go.jp/data/dataset/env_03_ds_131126_00000701

植物Ⅱ-蘚苔類 http://www.data.go.jp/data/dataset/env_03_ds_131126_00000701/resource/b03b0e7e-2470-4d8f-ab62-a815af3dcdb8

レッドリストの前提も目を通しておくと、理解がスムーズです。 http://www.biodic.go.jp/rdb/rdb_top.html

こちらのデータを使って、作業を進めて行きます。

R でデータ整形

閑話休題。データの準備をします。

DATA GO JPから、csv データをダウンロードします。 redlist_sy23.csv の中身は以下のようになっていました。

,分類群,目名,科名,和名,学名
絶滅(EX),苔類,ゼニゴケ目,ハマグリゼニゴケ科,ヒカリゼニゴケ,Cyathodium cavernarum Kunze
絶滅危惧Ⅰ類(CR+EN),蘚類,ナンジャモンジャゴケ目,ナンジャモンジャゴケ科,ナンジャモンジャゴケ,Takakia lepidozioides S.Hatt. & Inoue 

1行目から形式がおかしいですが、気にせずにさり気なく修正しながら、以下の処理を行います。

  • 英語でラベリング
  • 保全状況(絶滅危惧Ⅰ類...の部分)を英語化、列の最後尾へ
  • 学名は使用しないので削除
class,ordinal,family,japaneseName,rank
苔類,ゼニゴケ目,ハマグリゼニゴケ科,ヒカリゼニゴケ,EX

このcsvデータを R で希望する JSON形式に整形します。 (Rについては、こちら で記事を書きました)

formatted_csv <- read.csv("formatted_data.csv")

install.packages("RJSONIO")
library(RJSONIO)

makeRecursiveList <- function (x) {
  if (ncol(x) > 2) {
    listSplit <- split(x[-1], x[1], drop = TRUE)
    lapply(names(listSplit), function (y) { list(name = y, children = makeRecursiveList(listSplit[[y]])) })
  } else {
    lapply(seq(nrow(x[1])), function (y) { list(name = x[,1][y], rank = x[,2][y]) })
  }
}

jsonOutputData <- toJSON(list(name = "蘚苔類", children = makeRecursiveList(formatted_csv)))

write(jsonOutputData, "formatted_data.json")

ちょっと見づらいので JSONLintツールで整形したものがこちら。 http://jsonlint.com/

{
    "name": "蘚苔類",
    "children": [
        {
            "name": "ツノゴケ",
            "children": [
                {
                    "name": "ツノゴケ目",
                    "children": [
                        {
                            "name": "ツノゴケ科",
                            "children": [
                                {
                                    "name": "キノボリツノゴケ",
                                    "rank": "CR_EN"
                                },
                                {
                                    "name": "オガサワラキブリツノゴケ",
                                    "rank": "VU"
                                },
                                {
                                    "name": "ミドリツノゴケ",
                                    "rank": "VU"
                                }
                            ]
                        }
                    ]
                }
            ]
        },
...

これでデータの準備完了。

d3.js でビジュアライゼーション

radial layout の数値を調整して、アウトプット。

<!doctype html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>redlist</title>
  <script type="text/javascript" src="d3.v3.min.js"></script>
  <style type="text/css">
    .node circle {
      fill: #fff;
      stroke: steelblue;
      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 = 1500;
  
  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("formatted_data.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>

このようなアウトプットになりました。

  • 赤: 絶滅 (EX)
  • オレンジ: 絶滅寸前 (CR)/絶滅危惧 (EN)
  • 緑: 準絶滅危惧 (NT)
  • 青: 情報不足 (DD)

f:id:kuteken:20131225022621p:plain

こうして全体を俯瞰してみると、「苔類 ウロコゴケ目 ツボミゴケ科」に情報不足 (DD)の種が集中していることが特徴的でした。∴ツボミゴケ科に注目して観察に行くと、絶滅危惧種を救えるかもしれない!!

f:id:kuteken:20131225023114p:plain


 R でデータ整形することに慣れておらず、時間を取られ、d3.js の方で工夫ができなかったのですが、インタラクティブに経年比較、地域比較などができれば、もっとおもしろい見せ方が出来そうです。そして、実データを扱うには、データ整形や統計も勉強しなきゃダメなんだなーと実感。

 d3.js Advent Calendar 2013 を2回書かせていただいて、色々勉強になりました。同じことに興味を持っている方の存在を感じ取れたことは大変心強かったですし、アウトプットの機会をちゃんと持ちながら精進しなきゃいけないなと思いました。このような機会を提供いただき誠にありがとうございました。

明日で、Advent Calendar も最後ですね。ほんでは、みなさんよきクリスマスを。