[GIS] Skipping rows with CSV reader

arcpycsvgeometrypython

I have a CSV file which contains lat long coordinates which represent a car doing laps around a racetrack. At the end of each lap, there is a row in the CSV file which marks the end of the lap and does not follow the same format as the rest of the rows within the file. An example of such row would be "# Lap 1". I am trying to read through the file, pull out the lat long values, and create a polyline feature class which will display each of the laps. I have been able to create a single polyline but have not been able to create multiple polylines. I am trying to write the code so that when it recognizes the "#" at the beginning of the line, it will skip reading the line and start a new polyline.

I keep receiving the error:

RuntimeError: Point: Input value is not numeric.

I'm fairly new to Python and I'm not sure where to go from here.

Here is my code as it stands currently:

    import csv
    import arcpy

    #Function that creates polyline
    def addPolyline(fc, array, sr):
        polyline = arcpy.Polyline(array, sr)
        with arcpy.da.InsertCursor(fc, ("SHAPE@",)) as cursor:
            cursor.insertRow((polyline,))
        array.removeAll()

    arcpy.env.overwriteOutput = True
    arcpy.env.workspace = r"C:\GEOG 485\Lesson4"
    gpsTrack = open(arcpy.env.workspace + "\WakefieldParkRaceway_20160421.csv", "r")
    lineFC = "laplines.shp"
    sr = arcpy.SpatialReference(4326)
    arcpy.CreateFeatureclass_management(arcpy.env.workspace, lineFC, "POLYLINE", spatial_reference = sr)

    spatialRef = arcpy.Describe(lineFC).spatialReference

    csvReader = csv.reader(gpsTrack)
    header = next(csvReader)
    latIndex = header.index("Latitude")
    lonIndex = header.index("Longitude")
    timeIndex = header.index("Time") 

    #Create an empty array object
    vertexArray = arcpy.Array()

    #Loop through the line in the file and get each coordinate
    for row in csvReader:
        if row[timeIndex].startswith("#"):
            if vertexArray.count > 0:
                addPolyline(lineFC, vertexArray, spatialRef)

        lat = row[latIndex]
        lon = row[lonIndex]
        vertex = arcpy.Point(lon, lat)
        vertexArray.add(vertex)

    #Add polyline
    addPolyline(lineFC, vertexArray, spatialRef)

Best Answer

Your error is that when you find the end of the lap, you build the polyline but you keep executing the rest of the lines. To fix this you have different choices, one would be to use the else statement. Like this,

for row in csvReader:
    if row[timeIndex].startswith("#"):
        if vertexArray.count > 0:
            addPolyline(lineFC, vertexArray, spatialRef)
    else: # the statements in the else will only execute if it is not the end
        lat = row[latIndex]
        lon = row[lonIndex]
        vertex = arcpy.Point(lon, lat)
        vertexArray.add(vertex)

Just to give you another choice, you could also use continue key word, these will make the program to continue with the next iteration, something like this,

for row in csvReader:
    if row[timeIndex].startswith("#"):
        if vertexArray.count > 0:
            addPolyline(lineFC, vertexArray, spatialRef)
        continue # this will go on with the next iteration
    lat = row[latIndex]
    lon = row[lonIndex]
    vertex = arcpy.Point(lon, lat)
    vertexArray.add(vertex)

Two recommendations:

  • Use with to handle resources like files, it will take care of the clean up once the statements end.
  • I would reset the array vertexArray outside the function that insert, and add it right after addPolyline statement in the loop.

The first one is pretty important, the second one makes code easy to follow, cleaner, and keep the function simpler.

Related Question