Skip to content

Instantly share code, notes, and snippets.

@rutgerhofste
Created February 16, 2018 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rutgerhofste/6e7c6569616c2550568b9ce9cb4716a3 to your computer and use it in GitHub Desktop.
Save rutgerhofste/6e7c6569616c2550568b9ce9cb4716a3 to your computer and use it in GitHub Desktop.
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import geopandas as gpd"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from shapely.geometry import Polygon\n",
"\n",
"polys1 = gpd.GeoSeries([Polygon([(0,0), (2,0), (2,2), (0,2)]),\n",
" Polygon([(2,2), (4,2), (4,4), (2,4)])])\n",
"\n",
"\n",
"polys2 = gpd.GeoSeries([Polygon([(1,1), (3,1), (3,3), (1,3)]),\n",
" Polygon([(3,3), (5,3), (5,5), (3,5)]),\n",
" Polygon([(0,4), (1,4), (1,5), (0,5)])])\n",
"\n",
"\n",
"df1 = gpd.GeoDataFrame({'geometry': polys1, 'df1':[1,2]})\n",
"\n",
"df2 = gpd.GeoDataFrame({'geometry': polys2, 'df2':[1,2,3]})"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>df1</th>\n",
" <th>geometry</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2))</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" df1 geometry\n",
"0 1 POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))\n",
"1 2 POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2))"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df1"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>df2</th>\n",
" <th>geometry</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2</td>\n",
" <td>POLYGON ((3 3, 5 3, 5 5, 3 5, 3 3))</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3</td>\n",
" <td>POLYGON ((0 4, 1 4, 1 5, 0 5, 0 4))</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" df2 geometry\n",
"0 1 POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))\n",
"1 2 POLYGON ((3 3, 5 3, 5 5, 3 5, 3 3))\n",
"2 3 POLYGON ((0 4, 1 4, 1 5, 0 5, 0 4))"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def explode(gdf):\n",
" \"\"\" \n",
" Will explode the geodataframe's muti-part geometries into single \n",
" geometries. Each row containing a multi-part geometry will be split into\n",
" multiple rows with single geometries, thereby increasing the vertical size\n",
" of the geodataframe. The index of the input geodataframe is no longer\n",
" unique and is replaced with a multi-index. \n",
"\n",
" The output geodataframe has an index based on two columns (multi-index) \n",
" i.e. 'level_0' (index of input geodataframe) and 'level_1' which is a new\n",
" zero-based index for each single part geometry per multi-part geometry\n",
" \n",
" Args:\n",
" gdf (gpd.GeoDataFrame) : input geodataframe with multi-geometries\n",
" \n",
" Returns:\n",
" gdf (gpd.GeoDataFrame) : exploded geodataframe with each single \n",
" geometry as a separate entry in the \n",
" geodataframe. The GeoDataFrame has a multi-\n",
" index set to columns level_0 and level_1\n",
" \n",
" \"\"\"\n",
" gs = gdf.explode()\n",
" gdf2 = gs.reset_index().rename(columns={0: 'geometry'})\n",
" gdf_out = gdf2.merge(gdf.drop('geometry', axis=1), left_on='level_0', right_index=True)\n",
" gdf_out = gdf_out.set_index(['level_0', 'level_1']).set_geometry('geometry')\n",
" gdf_out.crs = gdf.crs\n",
" return gdf_out"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"df_all = df1.append(df2,ignore_index=True)\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>df1</th>\n",
" <th>df2</th>\n",
" <th>geometry</th>\n",
" <th>group</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1.0</td>\n",
" <td>NaN</td>\n",
" <td>POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0))</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2.0</td>\n",
" <td>NaN</td>\n",
" <td>POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2))</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>NaN</td>\n",
" <td>1.0</td>\n",
" <td>POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>NaN</td>\n",
" <td>2.0</td>\n",
" <td>POLYGON ((3 3, 5 3, 5 5, 3 5, 3 3))</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>NaN</td>\n",
" <td>3.0</td>\n",
" <td>POLYGON ((0 4, 1 4, 1 5, 0 5, 0 4))</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" df1 df2 geometry group\n",
"0 1.0 NaN POLYGON ((0 0, 2 0, 2 2, 0 2, 0 0)) 1\n",
"1 2.0 NaN POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2)) 1\n",
"2 NaN 1.0 POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1)) 1\n",
"3 NaN 2.0 POLYGON ((3 3, 5 3, 5 5, 3 5, 3 3)) 1\n",
"4 NaN 3.0 POLYGON ((0 4, 1 4, 1 5, 0 5, 0 4)) 1"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_all"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"df_all[\"group\"] = 1\n",
"dissolved = df_all.dissolve(by=\"group\")\n",
"gdf_out = explode(dissolved)\n",
"gdf_out2 = gdf_out.reset_index()\n",
"gdf_out2"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style>\n",
" .dataframe thead tr:only-child th {\n",
" text-align: right;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: left;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>level_0</th>\n",
" <th>level_1</th>\n",
" <th>geometry</th>\n",
" <th>df1</th>\n",
" <th>df2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>POLYGON ((2 1, 2 0, 0 0, 0 2, 1 2, 1 3, 2 3, 2...</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>POLYGON ((0 4, 0 5, 1 5, 1 4, 0 4))</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" level_0 level_1 geometry df1 \\\n",
"0 1 0 POLYGON ((2 1, 2 0, 0 0, 0 2, 1 2, 1 3, 2 3, 2... 1.0 \n",
"1 1 1 POLYGON ((0 4, 0 5, 1 5, 1 4, 0 4)) 1.0 \n",
"\n",
" df2 \n",
"0 1.0 \n",
"1 1.0 "
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gdf_out2"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x7f68952fd8d0>"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\nkgAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f68914697b8>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"gdf_out2.plot(column='level_1')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 35",
"language": "python",
"name": "python35"
},
"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.5.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment