Thursday, May 6, 2021

Python script to separate shapefile based on type (Point, Line and Polygon)

 Here I got a folder that contains several shapefiles of mixed types (i.e Point, Line and Polygon shapefiles all in the same folder), now I want separate each type of shapefile into one separate folder. That is all Point shapefiles into same folder, all Line shapefiles into same folder, and all Polygon shapefiles into same folder.


Here we got twelve shapefiles that look like this:-


To complete this manually, we have to open all the twelve files and save each to its respective folder. This is not we wanted and it is time consuming, so I will use python scripting to complete this.

Let's get our hands dirty...

There are several python modules/libraries for doing this, here I will use the Python Shapefile Library (PyShp). If I have the time, I will also do the same thing using the PyQGIS module/library. So make sure you have PyShp installed (pip install pyshp) in you python environment.

First, lets count the number of shapefiles for each type. Inspecting this in QGIS, shows we got 5 points shapefile, 2 lines shapefile and 5 polygons shapefile as seen below.


Using script, it looks like this...

import glob
import shapefile # pip install pyshp

# Read all the shp into a list...
shp_files = glob.glob(r'C:\Users\Yusuf_08039508010\Desktop\SHP folder_1\*.shp')

# Read the first shp from the list...
sf = shapefile.Reader(shp_files[0]) # Can also use: open(shp_files[0], "rb")

# The shpefile Type...
print(sf.shapeType)

# The shpefile Type Name...
print(sf.shapeTypeName)

Since the shapefile format is actually a collection of three or more files, with the PyShp library we can specify the base filename of the shapefile or the complete filename of any of the shapefile component files (.shp, .shx, .dbf, .prj, .cpg etc).

The we checked for the shapeType and shapeTypeName as 5 and POLYGON respectively. Shape types are represented by numbers between 0 and 31 as defined by the shapefile specification and listed below.
  • NULL = 0
  • POINT = 1
  • POLYLINE = 3
  • POLYGON = 5
  • MULTIPOINT = 8
  • POINTZ = 11
  • POLYLINEZ = 13
  • POLYGONZ = 15
  • MULTIPOINTZ = 18
  • POINTM = 21
  • POLYLINEM = 23
  • POLYGONM = 25
  • MULTIPOINTM = 28
  • MULTIPATCH = 31

Now that we know how to check the shapefile type, lets move the shapefiles in folder 1 to folder 2 base on their types as either Point, Lines or Polygon.

import glob
import shapefile # pip install pyshp
import shutil

# Paths to respective shp folders...
point_folder = r'C:\Users\Yusuf_08039508010\Desktop\Move SHP\SHP folder_2\points SHP'
line_folder = r'C:\Users\Yusuf_08039508010\Desktop\Move SHP\SHP folder_2\lines SHP'
polygon_folder = r'C:\Users\Yusuf_08039508010\Desktop\Move SHP\SHP folder_2\polygon SHP'

# Read all the shp into a list...
shp_files = glob.glob(r'C:\Users\Yusuf_08039508010\Desktop\Move SHP\SHP folder_1\*.shp')

for shp in shp_files:
    # Read the first shp from the list...
    sf = shapefile.Reader(shp) # Can also use: open(shp_files[0], "rb")
    print('Copying ', sf.shapeTypeName, 'shapefile...')
    
    # Check for shapefile type and copy to appropriate folder...
    if sf.shapeTypeName == 'POINT':
        shutil.copy(shp, point_folder)
        shutil.copy(shp.replace('.shp', '.dbf'), point_folder)
        shutil.copy(shp.replace('.shp', '.shx'), point_folder)
        shutil.copy(shp.replace('.shp', '.prj'), point_folder)
        shutil.copy(shp.replace('.shp', '.cpg'), point_folder)
        
    elif sf.shapeTypeName == 'POLYLINE':
        shutil.copy(shp, line_folder)
        shutil.copy(shp.replace('.shp', '.dbf'), line_folder)
        shutil.copy(shp.replace('.shp', '.shx'), line_folder)
        shutil.copy(shp.replace('.shp', '.prj'), line_folder)
        shutil.copy(shp.replace('.shp', '.cpg'), line_folder)
        
    elif sf.shapeTypeName == 'POLYGON':
        shutil.copy(shp, polygon_folder)
        shutil.copy(shp.replace('.shp', '.dbf'), polygon_folder)
        shutil.copy(shp.replace('.shp', '.shx'), polygon_folder)
        shutil.copy(shp.replace('.shp', '.prj'), polygon_folder)
        shutil.copy(shp.replace('.shp', '.cpg'), polygon_folder)
        
    else:
        print('This is neither point, line or polygon shapefile...')
        
print('Done...')

Note: to move the file use shutil.move(...)


That is it!

No comments:

Post a Comment