{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Chapter7\n", "D3.js in Actionの7章の勉強ノートです。\n", "\n", "最初にきちんと保存できるようにHTMLとd3.v3.min.jsをセットします。\n", "\n", "これまで、d3.v3.min.jsを以下のようにロードしていましたが、nvd3のinitialize_javascriptでこれが不要になりました。\n", "\n", "ただし、kernelはPython2を使用するため、sageは%load_extでロードします。\n", "\n", "``` html\n", "\n", "```" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The sage extension is already loaded. To reload it, use:\n", " %reload_ext sage\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "$.getScript(\"https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.js\")" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "$.getScript(\"https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js\", function() {\n", " $.getScript(\"https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.js\", function() {})});" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%load_ext sage\n", "from IPython.core.display import HTML\n", "from string import Template\n", "import json\n", "import nvd3\n", "nvd3.ipynb.initialize_javascript(use_remote=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "地図データをjupyterで表示することがD3を勉強し始めた契機でした。\n", "\n", "3章まで基本を勉強したので、ちょっと飛んで7章を試してみます。" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting css/ch7.css\n" ] } ], "source": [ "%%writefile css/ch7.css\n", "path.countries {\n", " stroke-width: 1;\n", " stroke: black;\n", " opacity: .5;\n", " fill: red;\n", "}\n", "circle.cities {\n", " stroke-width: 1;\n", " stroke: white;\n", " fill: black;\n", "}\n", "circle.centroid {\n", " fill: red;\n", " pointer-events: none;\n", "}\n", "rect.bbox {\n", " fill: none;\n", " stroke-dasharray: 5 5;\n", " stroke: black;\n", " stroke-width: 2;\n", " pointer-events: none;\n", "}\n", "path.graticule {\n", " fill: none;\n", " stroke-width: 1;\n", " stroke: black;\n", "}\n", "path.graticule.outline {\n", " stroke: black;\n", "}" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting js/ex7-1.js\n" ] } ], "source": [ "%%writefile js/ex7-1.js\n", "d3.json(\"js/world.geojson\", createMap);\n", "\n", "function createMap(countries) {\n", " var width = 350;\n", " var height = 350;\n", " var aProjection = d3.geo.mercator()\n", " .scale(80)\n", " .translate([width / 2, height / 2]);\n", " var geoPath = d3.geo.path().projection(aProjection);\n", " d3.select('#ex1').select(\"svg\").selectAll(\"path\").data(countries.features)\n", " .enter()\n", " .append(\"path\")\n", " .attr(\"d\", geoPath)\n", " .attr(\"class\", \"countries\")\n", "}" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%HTML\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "jupyterでqueueを使おうとするとエラーになってしまうので、queueを使わないで、citeisを表示してみます。" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting js/ex7-2.js\n" ] } ], "source": [ "%%writefile js/ex7-2.js\n", "d3.json(\"js/world.geojson\", createMap);\n", "\n", "var width = 350;\n", "var height = 350;\n", "var aProjection = d3.geo.mollweide()\n", " .scale(120)\n", " .rotate([-136, 0])\n", " .center([0, 38])\n", " .translate([width / 2, height / 2]);\n", "\n", "function createMap(countries) {\n", " var geoPath = d3.geo.path().projection(aProjection);\n", " var featureSize = d3.extent(countries.features,\n", " function(d) {return geoPath.area(d);}); \n", " var countryColor = d3.scale.quantize()\n", " .domain(featureSize).range(colorbrewer.Reds[7]);\n", " \n", " d3.select('#ex2').select(\"svg\").selectAll(\"path\").data(countries.features)\n", " .enter()\n", " .append(\"path\")\n", " .attr(\"d\", geoPath)\n", " .attr(\"class\", \"countries\")\n", " .style(\"fill\", function(d) {\n", " return countryColor(geoPath.area(d))\n", " });\n", "}\n", "\n", "d3.csv(\"data/cities.csv\",function(error,data) {createCities(data)});\n", "\n", "function createCities(cities) {\n", " d3.select('#ex2').select(\"svg\").selectAll(\"circle\").data(cities)\n", " .enter()\n", " .append(\"circle\")\n", " .attr(\"class\", \"cities\")\n", " .attr(\"r\", 3)\n", " .attr(\"cx\", function(d) { return aProjection([d.y, d.x])[0]})\n", " .attr(\"cy\", function(d) { return aProjection([d.y, d.x])[1]});\n", " \n", "}" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%HTML\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## タイルの利用\n", "タイルを使うと、地図の他に衛星写真やタイルに変換された地図情報を地図に重ね合わせて表示することができます。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting js/ex7-3.js\n" ] } ], "source": [ "%%writefile js/ex7-3.js\n", "var width = 500, height = 500;\n", "var takaokaBoundingBox = {geometry: {coordinates: [[[136.904778, 36.822525], [137.072662, 36.822525], [137.072662, 36.658552], [136.904778, 36.658552], [136.904778, 36.822525]]], type: \"Polygon\"}, id: 999999, properties:{}, type: \"Feature\"};\n", "\n", "d3.select(\"#ex3\").select(\"svg\").append(\"g\").attr(\"id\", \"tiles\");\n", "d3.select(\"#ex3\").select(\"svg\").append(\"g\").attr(\"id\", \"vectors\");\n", "\n", "var tile = d3.geo.tile()\n", " .size([width, height]);\n", "\n", "var projection = d3.geo.mercator()\n", " .scale((1 << 19) / 2 / Math.PI)\n", " .translate([width / 2, height / 2]);\n", "\n", "var center = projection([137.025970, 36.754062]);\n", "\n", "var path = d3.geo.path()\n", " .projection(projection);\n", "var zoom = d3.behavior.zoom()\n", " .scale(projection.scale() * 2 * Math.PI)\n", " .translate([width - center[0], height - center[1]])\n", " .on(\"zoom\", redraw);\n", "d3.select(\"#ex3\").select(\"svg\").call(zoom);\n", "projection\n", " .scale(1 / 2 / Math.PI)\n", " .translate([0, 0]);\n", "\n", "\n", "var geoPath = d3.geo.path().projection(projection);\n", "d3.select(\"#ex3\").select(\"#vectors\").selectAll(\"path.countries\").data([takaokaBoundingBox])\n", " .enter()\n", " .append(\"path\")\n", " .attr(\"d\", geoPath)\n", " .attr(\"class\", \"countries\")\n", " .style(\"fill\", \"red\")\n", " .style(\"stroke-width\", 3)\n", " .style(\"stroke\", \"black\")\n", " .style(\"fill-opacity\", .25)\n", "\n", "redraw();\n", "\n", "function redraw() {\n", " var tiles = tile\n", " .scale(zoom.scale())\n", " .translate(zoom.translate())();\n", " \n", " var image = d3.select(\"#ex3\").select(\"#tiles\")\n", " .attr(\"transform\",\n", " \"scale(\" + tiles.scale + \") translate(\" + tiles.translate + \")\")\n", " .selectAll(\"image\")\n", " .data(tiles, function(d) { return d; });\n", " \n", " image.exit()\n", " .remove();\n", "\n", " image.enter().append(\"image\")\n", " .attr(\"xlink:href\",\n", " function(d) { return \"http://\" \n", " + [\"a\", \"b\", \"c\"][Math.random() * 3 | 0] \n", " + \".tile.openstreetmap.org/\" + d[2] + \"/\" + d[0] + \"/\" + d[1] \n", " + \".png\"; }) \n", " .attr(\"width\", 1)\n", " .attr(\"height\", 1)\n", " .attr(\"x\", function(d) { return d[0]; })\n", " .attr(\"y\", function(d) { return d[1]; });\n", " \n", " projection\n", " .scale(zoom.scale() / 2 / Math.PI)\n", " .translate(zoom.translate());\n", "\n", " d3.select(\"#ex3\").selectAll(\"path\")\n", " .attr(\"d\", geoPath);\n", "}" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%HTML\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### shpファイルからgeojsonを作成\n", "\n", "gdal-binをインストール\n", "```bash\n", "$ sudo apt-get install -y gdal-bin\n", "```\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "ERROR 6: The GeoJSON driver does not overwrite existing files.\n", "geoJSON driver failed to create data/A27-10_16-g_SchoolDistrict.json\n" ] } ], "source": [ "%%bash\n", "# rm -f data/A27-10_16-g_SchoolDistrict.json\n", "ogr2ogr -f geoJSON data/A27-10_16-g_SchoolDistrict.json data/A27-10_16-g_SchoolDistrict.shp" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting js/ex7-4.js\n" ] } ], "source": [ "%%writefile js/ex7-4.js\n", "var width = 500, height = 500;\n", "var takaokaBoundingBox = {geometry: {coordinates: [[[136.904778, 36.822525], [137.072662, 36.822525], [137.072662, 36.658552], [136.904778, 36.658552], [136.904778, 36.822525]]], type: \"Polygon\"}, id: 999999, properties:{}, type: \"Feature\"};\n", "\n", "d3.select(\"#ex4\").select(\"svg\").append(\"g\").attr(\"id\", \"tiles\");\n", "d3.select(\"#ex4\").select(\"svg\").append(\"g\").attr(\"id\", \"vectors\");\n", "\n", "var tile = d3.geo.tile()\n", " .size([width, height]);\n", "\n", "var projection = d3.geo.mercator()\n", " .scale((1 << 19) / 2 / Math.PI)\n", " .translate([width / 2, height / 2]);\n", "\n", "var center = projection([137.025970, 36.754062]);\n", "\n", "var path = d3.geo.path()\n", " .projection(projection);\n", "var zoom = d3.behavior.zoom()\n", " .scale(projection.scale() * 2 * Math.PI)\n", " .translate([width - center[0], height - center[1]])\n", " .on(\"zoom\", redraw);\n", "d3.select(\"#ex4\").select(\"svg\").call(zoom);\n", "projection\n", " .scale(1 / 2 / Math.PI)\n", " .translate([0, 0]);\n", "\n", "var geoPath = d3.geo.path().projection(projection);\n", "\n", "d3.json('data/A27-10_16-g_SchoolDistrict.json', function (schoolDistnct) {\n", " // console.log(schoolDistnct);\n", "\n", " var data = schoolDistnct.features.filter(function(d) { \n", " return d.properties.A27_006==\"高岡市立\"; \n", " });\n", "\n", " d3.select(\"#ex4\").select(\"#vectors\").selectAll(\"path.countries\").data(data)\n", " .enter()\n", " .append(\"path\")\n", " .attr(\"d\", geoPath)\n", " .attr(\"class\", \"countries\")\n", " .style(\"fill\", \"red\")\n", " .style(\"stroke-width\", 3)\n", " .style(\"stroke\", \"black\")\n", " .style(\"fill-opacity\", .25) \n", " \n", "}); \n", "\n", "redraw();\n", "\n", "function redraw() {\n", " var tiles = tile\n", " .scale(zoom.scale())\n", " .translate(zoom.translate())();\n", " \n", " var image = d3.select(\"#ex4\").select(\"#tiles\")\n", " .attr(\"transform\",\n", " \"scale(\" + tiles.scale + \") translate(\" + tiles.translate + \")\")\n", " .selectAll(\"image\")\n", " .data(tiles, function(d) { return d; });\n", " \n", " image.exit()\n", " .remove();\n", "\n", " image.enter().append(\"image\")\n", " .attr(\"xlink:href\",\n", " function(d) { return \"http://\" \n", " + [\"a\", \"b\", \"c\"][Math.random() * 3 | 0] \n", " + \".tile.openstreetmap.org/\" + d[2] + \"/\" + d[0] + \"/\" + d[1] \n", " + \".png\"; }) \n", " .attr(\"width\", 1)\n", " .attr(\"height\", 1)\n", " .attr(\"x\", function(d) { return d[0]; })\n", " .attr(\"y\", function(d) { return d[1]; });\n", " \n", " projection\n", " .scale(zoom.scale() / 2 / Math.PI)\n", " .translate(zoom.translate());\n", "\n", " d3.select(\"#ex4\").selectAll(\"path\")\n", " .attr(\"d\", geoPath);\n", "}" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%HTML\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", " \n", " \n", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "geojsonのデータは、以下の図のように各gの__data__属性に保持されています。" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }