{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import geopandas as gpd\n", "import pandas as pd\n", "import numpy as np\n", "df = gpd.read_file(\"data/semiology_of_graphics.geojson\").set_index(\"code\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# generate a grid\n", "\n", "grain = 30\n", "x1, y1, x0, y0 = df.total_bounds\n", "xv, yv = np.meshgrid(\n", " np.linspace(x0, x1, grain), \n", " np.linspace(y0, y1, grain)\n", ")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# uncomment to get a hexagonal grid\n", "\n", "# delta = (yv[0,0] - yv[1,0])/4\n", "# a = np.empty((grain,))\n", "# a[::2] = delta\n", "# a[1::2] = -delta\n", "# yv += a" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# create a new data frame of points and figure out which department each points is in\n", "\n", "gdf = gpd.GeoDataFrame(geometry=gpd.points_from_xy(xv.flatten(), yv.flatten())).set_crs(df.crs)\n", "\n", "codes = []\n", "\n", "for point in gdf.geometry:\n", " code = None\n", " for index, row in df.iterrows():\n", " if point.within(row.geometry):\n", " code = index\n", " continue\n", " codes.append(code)\n", " \n", "# force a couple of points in the top right to be Paris and Seine\n", "codes[3] = \"P\"\n", "codes[5] = \"75\"\n", "\n", "gdf[\"code\"] = codes\n", "\n", "# drop any points that didn't fall into a department\n", "gdf = gdf.dropna()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# figure out how many points fell within each department\n", "\n", "gdf = gdf.merge(\n", " pd.DataFrame((1/gdf.code.value_counts().rename(\"department_fraction\")).reset_index()), \n", " left_on=\"code\", right_on=\"index\"\n", ").drop(\"index\", axis=1)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# merge the department data and allocate it among the points in each department\n", "\n", "gdf = gdf.merge(df[['agriculture', 'industry', 'services', 'department', 'total']].reset_index())\n", "gdf.total = (gdf.total * gdf.department_fraction).astype(int)\n", "gdf.agriculture = (gdf.agriculture * gdf.department_fraction).astype(int)\n", "gdf.industry = (gdf.industry * gdf.department_fraction).astype(int)\n", "gdf.services = (gdf.services * gdf.department_fraction).astype(int)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# uncomment to save the file\n", "\n", "# gdf.to_file(\"data/semiology_of_graphics_points.geojson\", driver=\"GeoJSON\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# plot the resulting `services` data\n", "\n", "import plotly.express as px\n", "\n", "fig = px.scatter_geo(gdf, lat=gdf.geometry.y, lon=gdf.geometry.x, \n", " size=\"services\", size_max=30, fitbounds=\"geojson\", \n", " projection=\"mercator\", basemap_visible=False)\n", "basepolygons = (\n", " px.choropleth(df, geojson=df.geometry, locations=df.index, color_discrete_sequence=[\"white\"])\n", " .update_traces(marker_line_color=\"lightgrey\", showlegend=False)\n", " .data[0]\n", ")\n", "\n", "fig.update_layout(showlegend=False, height=400, margin=dict(t=40, b=0, r=0, l=0))\n", "fig.add_trace(basepolygons)\n", "fig.show(\"svg\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" }, "widgets": { "state": { "9231b4c2e8414372a9cf5e8d4a6557c9": { "views": [] }, "d85eb0ebf010455cb8d50f3a339fb78a": { "views": [ { "cell_index": 1 } ] } }, "version": "1.1.2" } }, "nbformat": 4, "nbformat_minor": 4 }