There’s no immediate way to export a GeoDataFrame to an SVG through, say, a Geopandas API method. That said, shapely object have a
.svg() method that opens up the possibility for a GDF to SVG method to be easily developed. This post demonstrates a quick and dirty way of accomplishing this. It uses the
data-* tag available on SVG elements to add each row value other than the geometry to each grouped row element.
The GDF to SVG method will group each row in a single group
<g> tag. This allows that group tag (
<g>) to hold all items from that row that are not the geometry value in
data- tag form. A given row may have many polygons associated with it (held in a MultiPolygon). This allows the each polygon in that MultiPolygon to be nested within the group and the data attributes to be associated with those geometries only once. This is sufficient for portability and, for example, loading the associated data into a vector graphics tool like Adobe Illustrator, should that be desired (say you wanted to make a styled graphic of a GDF).
For this exercise, I will use the zoning dataset from San Rafael, available here. This is a simple, typical Shapefile dataset that can be downloaded and loaded into Geopandas easily.
We can load it in pretty easily, and plot it:
This will result in the above graphic.
Adjusting the coordinates
Now that we have the Shapefile converted to a GeoDataFrame, we need to adjust the coordinates so that they are “pushed” relative to a 0,0 coordinate position that represents the minimum x and y value from the coordinates of the GDF.
The below script does this. It finds the minimum x and y value and then, for each polygon (of each MultiPolygon) of each row, it shifts the x and y coordinates down so that the minimum of each axis then equals 0.
We can check this result by plotting it again, this time with coordinates.
As we can see from the above result, the values are now relative to a 0,0 bottom left starting point.
Converting to an SVG string
At this point, we can just take a string representation of an SVG and replace the body of the SVG with the data pulled out from the rows in the GDF. We can first format each row using the below method.
In this method, we use the Shapely SVG method to get a string of the SVG, then we add the other row values in the top level
<g> tag. Note that the returned SVG is defaulted to a green color if it is valid in Shapely and a red color if it is not. We can parse the returned string if we want to and change the color to whatever we want. For example, we could extract the viridis color scheme for the Geopandas plot and use that color result to apply the same colors to the geometries contained in each row and pulled out, here. I won’t go through the hassle in this post, but it is about as simple as adding in the data tags.
Speaking of data tages, we can insert those processed rows of the GDF into an SVG element, along with a bunch of standard default SVG tags. I also am going to set the width and height to a 100% so that the SVG will just scale to its parent
Finally, we can write the file to local storage, like so:
This isn’t a particularly optimized operation, but it looks like it runs decently. Running it in a loop 100x took about 99 seconds, so about 0.99 seconds per run. What I timed was the conversion to formatted string (so avoiding the IO part).
Given that performance on 1,801 row GeoDataFrame, we can assume that this should run decently quickly on larger data frames (particularly if a simplification step is included, as I did in this, to keep outputs at a reasonable level of detail.
Without simplification, the output file was 4.1 MB. With the 5 or 10 meter simplification (both were tried), it fall just below 1 MB.
To close out, here’s the SVG, embedded for download/to oogle at/etc.
Or as a Gist: