{
"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
}