[GIS] Creating records in output shapefile using Python

gdalogrpythonshapefile

I have a list (output from a previous loop) containing attributes from an input shapefile. What I am stuck with is inputting those attributes to a new shapefile.

I have plotted the point data using w.point(x, y) and also created the relevant fields w.field() from the input shapefile fields.

Where I am stuck is with the copy of the records, which is giving me an Error related to Deletion Flag.

AttributeError: 'tuple' object has no attribute 'startswith'

I am pasting a section of the code with my queries.

from datetime import datetime
import osgeo.ogr, osgeo.ogr
from osgeo import ogr
from osgeo import gdal
import shapefile
import os

sf = shapefile.Reader("-- Input File Location --") # Reading the Shapefile
fields = sf.fields # Reading the attribute fields
records = sf.records() # Reading the records of the features
shapRecs = sf.shapeRecords() # Read Geometry and Records simultaneously 

w = shapefile.Writer(shapefile.POINT)
w.autoBalance = 1
result1 = []
result2 = [] # ??? Is the error because we cannot query for list in a list ???

print '** Call function pt(p) where p is node index... **' # Prompting the user to 
                                                           # call the function with 
                                                           # the required number of nodes
def pt(p):
    for i in range(len(shapRecs)):
        u = shapRecs[i].shape.points[p-1]   # Gives the XY Coordinates of
                                            # the queried points

        v = shapRecs[i].record[0:]          # Generating the Attributes
        result1.append(u)
        result2.append(v)

        w.point(u[0], u[1]) # Create points from coordinates each time the loop runs
        w.autoBalance = 1

    # -- Adding the fields
    w.field(fields[0]) # Adding the first field, WITH Deletion Flag (???)
    for i in range(1, len(fields)): # Loop begins from the second field (???)
        w.field(fields[i])
        w.autoBalance = 1

    # CODE SHOWS THE ERROR STATED ABOVE FROM THE w.record() statement
    # -- Adding the records 
    for i in range(len(result2)):
        w.record(*result2[i])       
        w.autoBalance = 1

    w.save('-- Output File Location --')    

Best Answer

I don't understand your script. Why use PyShp (shapefile), if you use osgeo.ogr ? You could do the same thing with ogr only ( better way to duplicate a layer using ogr in python? ).

If you want to import ogr and gdal from osgeo, the formulation

import osgeo.ogr, osgeo.ogr
from osgeo import ogr
from osgeo import gdal

is a redundancy (you import ogr and gdal twice)

Same for sf.records()and sf.shapeRecords():

sf = shapefile.Reader("strati")
records = sf.records() # Reading the records of the features
for rec in records:
   print rec 
[30, 130, 'incl']
[55, 145, 'incl']
[40, 155, 'incl']

and

shapRecs = sf.shapeRecords()
for rec in shapRecs:
     print rec.record
[30, 130, 'incl']
[55, 145, 'incl']
[40, 155, 'incl']

If you only want the geometry:

 for rec in sf.iterShapes():
     x,y = rec.points[0]
     print x,y
 272070.600041, 155389.3879200000
 271066.03214800003, 154475.63137700001
 273481.498868, 153923.49298800001

and

for rec in shapRecs:
    x,y = rec.shape.points[0]

If you just want to copy the shapefile:

w = shapefile.Writer(shapefile.POINT)
sf = shapefile.Reader("strati")
w.fields = list(sf.fields)
for rec in sf.records():
    w.records.append(rec)
    w._shapes.extend(sf.shapes())
w.save("duplicate") 

If you want to add a Field, look at Add a Field to an Existing Shapefile

If you want lists, the easiest way is:

sf = shapefile.Reader("yourfile.shp")
shapes = sf.shapes() # -> list of all the geometries
fields = sf.fields[1:] #-> fields definition in a list (without the Deletion Flag)
field_names = = [field[0] for field in fields] #-> list of fields names
attributes = sf.records() #-> list with all the attributes