Datamate.jsを使ったサンプル
Datamate.jsライブラリを使ったサンプルを示します。自分の発掘したデータを視覚化するプログラムを作る際の参考にしてください。サンプル1:人を死に至らしめる動物
世界で、1年間に何人が、どんな動物に殺されているか?その情報が、The Blog of Bill Gatesのサイトで公開されています。 そのトップが「蚊」で、蚊を退治することが人々、特に開発途上国の人たちに重要であることを伝える目的の情報です。World’s Deadliest Animalsのデータを使い、動物に殺された人数を視覚化してみます。
2015年のデータをCSVファイルDeadlyAnimal.csvとして用意しました。
このファイルの中身は次のような内容です。

【サンプルその1】 // 人を殺す動物 const title = "死を招く動物とその被害者数(2015年)"; const d = 4; function setup() { createCanvas(750, 770); Datamate.make("DeadlyAnimal.csv"); Datamate.makeAreas(0, 0, width, height, 6, 3); Datamate.bindAreas([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ,15]); } function draw() { background(240); for (let i=0; i<Datamate.columnCount(); i++) { drawData(i); } textAlign(LEFT, CENTER); print(title); text(title, 30, 15); //データ名の表示 } function drawData(index) { const area = Datamate.area(index); const name = Datamate.columnName(index);//列のヘッダ const value = Datamate.value(0, index); const count = map(value, 1, 830000, 1, 1500); //円の個数 //print(index + " " + (area.height/d) + " " + (area.width/d)); stroke(200); noFill(); rect(area.left, area.top, area.width, area.height); // エリアの矩形を描画 noStroke(); fill(200, 0, 0); let n = 0; out: //個数分の円を描き終わったら、二重ループを抜けるために先頭にoutというラベルをつけた for (let j=0; j<area.height/d; j++) { for (let i=0; i<area.width/d-1; i++) { //area.width/dで、areaの幅に並べられる直径dの円の個数を計算 n++; if (n>count) { break out; //円をcountの個数まで書いたらoutというラベルがついている二重ループを終了 } circle(area.left+(i+1)*d, area.bottom-(j+1)*d-30, d); //円を書く } } fill(0); textAlign(CENTER, CENTER); text(name, area.centerX, area.bottom-25); text(value+"人", area.centerX, area.bottom-10); }
サンプル2:世界人助け指数
Charities Aid Foundationは、THE WORLD GIVING INDEX2021をその Webサイトで公開しています。
- ・過去1ヵ月の間に見知らぬ人を助けたか
- ・寄付をしたか
- ・ボランティアをしたか
右のようなデータです。 このcsvファイルを次のように読み込んでも、
Datamate.make("Giving.csv");
あるいは、次のように、行ごとのデータを配列で指定しても同じです。
Datamate.make("国名", ["全体", "手助け", "寄付", "ボランティア"]); Datamate.make("インドネシア", [69, 65, 83, 60]); Datamate.make("ケニア", [58, 76, 49, 49]); Datamate.make("オーストラリア", [49, 57, 61, 30]); Datamate.make("アメリカ", [43, 58, 45, 26]); Datamate.make("ウクライナ", [41, 65, 28, 31]); Datamate.make("フィリピン", [33, 62, 16, 23]); Datamate.make("ロシア", [33, 57, 28, 14]); Datamate.make("韓国", [22, 29, 28, 10]); Datamate.make("イタリア", [22, 33, 23, 9]); Datamate.make("日本", [12, 12, 12, 12]);
【サンプルその2】 const title = "世界人助け指数"; const keisu = 0.05; let currentA = []; //項目ごとの途中の角度 function setup() { createCanvas(600, 300); //Datamate.make("Giving.csv"); //行ヘッダが国名 Datamate.make("国名", ["全体", "手助け", "寄付", "ボランティア"]); Datamate.make("インドネシア", [69, 65, 83, 60]); Datamate.make("ケニア", [58, 76, 49, 49]); Datamate.make("オーストラリア", [49, 57, 61, 30]); Datamate.make("アメリカ", [43, 58, 45, 26]); Datamate.make("ウクライナ", [41, 65, 28, 31]); Datamate.make("フィリピン", [33, 62, 16, 23]); Datamate.make("ロシア", [33, 57, 28, 14]); Datamate.make("韓国", [22, 29, 28, 10]); Datamate.make("イタリア", [22, 33, 23, 9]); Datamate.make("日本", [12, 12, 12, 12]); Datamate.makeAreas(0, 30, width, height, 5, 2); Datamate.bindAreas([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); Datamate.play(0.1, 0); // 横方向に動かす Datamate.loop(true, false); angleMode(DEGREES); //Datamate.plot();// データを表示 for (let i=0; i<Datamate.rowCount(); i++) { currentA[i] = 0; //最初、角度はゼロ } } function draw() { background(240); for (let i=0; i<Datamate.rowCount(); i++) { drawData(i); // データiを描画 } } function drawData(number) { const area = Datamate.area(number); // エリアをとりだす const index = Datamate.focusX(1); //今フォーカスしているデータの次のインデックス const indexHokan = Datamate.focusX(0, true); //今フォーカスしているデータと次のデータの間 const syurui = Datamate.columnName(index); //列のヘッダ 寄付などのデータ種名 const country = Datamate.rowName(number); //行のヘッダ const value = Datamate.value(country, indexHokan); strokeWeight(8); //線を太く noFill(); stroke(200, 0, 0); let targetA = map(value, 0, 100, 0, 360); //データを円の角度に換算 currentA[number] = currentA[number] + (targetA - currentA[number]) * keisu; //角度少しずつ変化 //顔の輪郭、円弧の長さでデータを表す。 -90度は時計の12の位置 arc(area.centerX, area.centerY, area.width-15, area.width-15, -90, currentA[number]-90); strokeWeight(5); if (dist(mouseX, mouseY, area.centerX, area.centerY) < (area.width-15)/2) { //マウスが円内に入ったら、 ellipse(area.centerX, area.centerY+20, 20, 10); //口 }else{ arc(area.centerX, area.centerY+20, 20, 10, 0, 180); //口 } noStroke(); fill(200, 0, 0); circle(area.centerX-12, area.centerY-20, 8); //目 circle(area.centerX+12, area.centerY-20, 8); fill(0); textAlign(LEFT, CENTER); text(title+"("+syurui+")", 30, 30); //データ名の表示 textAlign(CENTER, CENTER); text(country + "\n" + Datamate.value(country, index) + "%", area.centerX, area.centerY); }
サンプル3:女性への学部学位授与課程への入学許可年
大学において、女性が男性と同じ基準で学部の学位授与課程への入学を認められた年を10の大学で比較します。 (女性の世界地図, 明石書店, p.152より引用)開学年を表す黒円上で、マウスを押下すると、赤円が開学年のところまで戻り、右への移動を再開します。
大学ごとの開学年、女性入学許可年を記した、UnivWomen.csvを用意しました。
次のようなデータです。

Datamate.make("UnivWomen.csv");
【サンプルその3】 const title = "女性への学部学位授与課程への入学許可年"; let d = 30; //円の直径 let currentX = []; //大学ごとの赤円の位置 function setup() { createCanvas(700, 500); Datamate.make("UnivWomen.csv"); Datamate.makeAreas(0, 50, width, height, 1, 10); Datamate.bindAreas([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); textAlign(LEFT, CENTER); for (let i=0; i<Datamate.columnCount(); i++) { currentX[i] = 0; //最初、赤円の位置は左端 } } function draw() { background(240); noStroke(); textAlign(LEFT, CENTER); textSize(15); text(title, 30, 30); //データタイトルの表示 fill(200, 0, 0); circle(340, 30, d); //データタイトル右の赤い円 fill(0); circle(370, 30, d); //データタイトル右の黒い円 textAlign(CENTER, CENTER); textSize(8); //文字サイズを8ピクセルにする fill(255); text("開学年", 370, 30); //データタイトル右の黒円の上に文字を描く for (let i=0; i<Datamate.columnCount(); i++) { drawData(i); // データiを描画 } } function drawData(index) { const area = Datamate.area(index); // 割り当てられたエリアをとりだす const open = Datamate.value(Datamate.rowName(0), index); const women = Datamate.value(Datamate.rowName(1), index); strokeWeight(5); //線を太く noFill(); stroke(0); line(area.left+140, area.centerY, area.right-10, area.centerY); //横線を描く noStroke(); textSize(8); //開学の年 黒い円 const openPos = map(open, 1100, 2020, area.left+140, area.right-10); fill(0); circle(openPos, area.centerY, d); textAlign(CENTER, CENTER); fill(255); text(open, openPos, area.centerY); //円の上に文字を描く //女子学生入学年 赤い円 const womenPos = map(women, 1100, 2020, area.left+140, area.right-10); fill(200, 0, 0); currentX[index] = lerp(currentX[index], womenPos, 0.02); //右へ少しずつ動く circle(currentX[index], area.centerY, d); textAlign(CENTER, CENTER); fill(255); text(women, currentX[index], area.centerY); //円の上に文字を描く //黒円上で、マウス押下すると、赤円が開学のところまで戻り、移動を再開 if (mouseIsPressed && dist(mouseX, mouseY, openPos, area.centerY)<d/2) { currentX[index] = openPos; //赤円の位置を開学のところへ fill(0); //黒円を書く準備 circle(openPos, area.centerY, d); textAlign(CENTER, CENTER); fill(255); text(open, openPos, area.centerY); //円の上に文字を描く } fill(0); textAlign(LEFT, CENTER); textSize(12); text(Datamate.columnName(index)+"大学", area.left+10, area.centerY); }
サンプル4:人を死に至らしめる動物ー別の表現
サンプル1の「人を死に至らしめる動物」では、人数を表す赤丸は四角形の中に並べて表示されるだけで動きません。 「蚊」や「人間」に殺される人数を強調するため、上から円が落ちてきて溜まるビジュアルにしたのが下です。クリックで再起動
重力場の中で落下する物体(この例では赤丸)の位置の計算を、物理計算ライブラリ Matters.jsを使っています。
同じデータでも、視覚化の仕方次第で、人に伝えるインパクトがかわります。さまざまに工夫してしてみてください。