How to create a point/line/polygon shapefile with Python and Fiona - Tutorial
/Storage, management and analysis of geospatial vector data as an ESRI shapefile is a common procedure of GIS and related professionals. The generation of these spatial files can be done not only on a desktop software but also by Python commands. We have created an applied example that shows the procedure in Python to create point, line, and polygon shapefiles from a csv file by the use of the Fiona library.
If you are a Windows user, it is recommended to have Fiona and other geospatial libraries installed under a Conda environment following this tutorial.
Tutorial
Python code
#import requires packages
import fiona
import pandas as pd
Create point shapefile
#import points from csv file
pointDf = pd.read_csv('../Txt//cropPoints.csv',header=0)
pointDf.head()
X | Y | Name | |
---|---|---|---|
0 | -84.200969 | 9.480966 | Plant1 |
1 | -84.200841 | 9.480931 | Plant2 |
2 | -84.201841 | 9.481167 | Plant3 |
3 | -84.200862 | 9.479898 | Plant4 |
4 | -84.200657 | 9.479586 | Plant5 |
# define schema
schema = {
'geometry':'Point',
'properties':[('Name','str')]
}
# explore available drivers
fiona.supported_drivers
{'AeronavFAA': 'r',
'ARCGEN': 'r',
'BNA': 'rw',
'DXF': 'rw',
'CSV': 'raw',
'OpenFileGDB': 'r',
'ESRIJSON': 'r',
'ESRI Shapefile': 'raw',
'FlatGeobuf': 'rw',
'GeoJSON': 'raw',
'GeoJSONSeq': 'rw',
'GPKG': 'raw',
'GML': 'rw',
'OGR_GMT': 'rw',
'GPX': 'rw',
'GPSTrackMaker': 'rw',
'Idrisi': 'r',
'MapInfo File': 'raw',
'DGN': 'raw',
'PCIDSK': 'rw',
'OGR_PDS': 'r',
'S57': 'r',
'SEGY': 'r',
'SQLite': 'raw',
'SUA': 'r',
'TopoJSON': 'r'}
#structure of fiona object
fiona.open( fp, mode='r', driver=None, schema=None, crs=None, encoding=None, layer=None, vfs=None, enabled_drivers=None, crs_wkt=None, **kwargs, )
#open a fiona object
pointShp = fiona.open('../ShapeOut/cropPoints.shp', mode='w', driver='ESRI Shapefile',
schema = schema, crs = "EPSG:4326")
#iterate over each row in the dataframe and save record
for index, row in pointDf.iterrows():
rowDict = {
'geometry' : {'type':'Point',
'coordinates': (row.X,row.Y)},
'properties': {'Name' : row.Name},
}
pointShp.write(rowDict)
#close fiona object
pointShp.close()
Create line shapefile
#import line vertex from csv file
lineDf = pd.read_csv('../Txt/cropLine.csv',header=0)
lineDf.head()
X | Y | Name | |
---|---|---|---|
0 | -84.201990 | 9.480380 | Row1 |
1 | -84.201928 | 9.480319 | Row1 |
2 | -84.201871 | 9.480261 | Row1 |
3 | -84.201820 | 9.480199 | Row1 |
4 | -84.201756 | 9.480133 | Row1 |
# define schema
schema = {
'geometry':'LineString',
'properties':[('Name','str')]
}
#open a fiona object
lineShp = fiona.open('../ShapeOut/cropLine.shp', mode='w', driver='ESRI Shapefile',
schema = schema, crs = "EPSG:4326")
#get list of points
xyList = []
rowName = ''
for index, row in lineDf.iterrows():
xyList.append((row.X,row.Y))
rowName = row.Name
xyList[:5]
[(-84.2019904893069, 9.48038022019686),
(-84.2019279965972, 9.48031926246447),
(-84.2018711206848, 9.48026145133191),
(-84.2018196550243, 9.48019910289781),
(-84.2017559092017, 9.48013268586072)]
#save record and close shapefile
rowDict = {
'geometry' : {'type':'LineString',
'coordinates': xyList},
'properties': {'Name' : rowName},
}
lineShp.write(rowDict)
#close fiona object
lineShp.close()
Create polygon shapefile
#import line vertex from csv file
polyDf = pd.read_csv('../Txt/cropPoly.csv',header=0)
polyDf.head()
X | Y | Name | |
---|---|---|---|
0 | -84.202396 | 9.480334 | Border1 |
1 | -84.202190 | 9.480555 | Border1 |
2 | -84.201886 | 9.480792 | Border1 |
3 | -84.201529 | 9.481153 | Border1 |
4 | -84.201307 | 9.481303 | Border1 |
#show the last item
polyDf.tail()
X | Y | Name | |
---|---|---|---|
19 | -84.201742 | 9.479385 | Border1 |
20 | -84.201863 | 9.479413 | Border1 |
21 | -84.202157 | 9.479673 | Border1 |
22 | -84.202398 | 9.479917 | Border1 |
23 | -84.202396 | 9.480334 | Border1 |
# define schema
schema = {
'geometry':'Polygon',
'properties':[('Name','str')]
}
#open a fiona object
polyShp = fiona.open('../ShapeOut/cropPoly.shp', mode='w', driver='ESRI Shapefile',
schema = schema, crs = "EPSG:4326")
#get list of points
xyList = []
rowName = ''
for index, row in polyDf.iterrows():
xyList.append((row.X,row.Y))
rowName = row.Name
xyList[:5]
[(-84.20239642444, 9.48033431305493),
(-84.2021899231741, 9.48055508704213),
(-84.2018864783201, 9.48079161161365),
(-84.2015288437831, 9.48115260231102),
(-84.2013071850694, 9.4813034753504)]
#save record and close shapefile
rowDict = {
'geometry' : {'type':'Polygon',
'coordinates': [xyList]}, #Here the xyList is in brackets
'properties': {'Name' : rowName},
}
polyShp.write(rowDict)
#close fiona object
polyShp.close()
Input data
You can download the input data from this link.