Select to view content in your preferred language

convert a csv with wkt geometry to featureclass with all attributes

12334
15
Jump to solution
02-16-2021 01:04 PM
BrookeHodge
Regular Contributor

Hi,

I'm trying to take a csv that was created from a pandas dataframe that has a wkt string as the geometry information (it's a line geometry), and create a line feature class containing all the fields within the csv (15 or so).  I can use the arcpy.FromWKT to crate a geometry object and can put that into a list, and use the arcpy.CopyFeatures_management to create a featureclass from that list, however, it doesn't contain any other fields from the CSV, it only contains the geometry, so just creates a line.  

Here for a test, I'm just trying to bring over 1 other field (id).  I have tried creating a list of lists with it, but I get an error with the CopyFeatures function that it doesn't like that.

I can also use a .da.insertcursor to get each value for each field and and write it out to a file row by row, but I have about 15 fields with millions and millions of rows and feel like there needs to be a more computationally efficient way of doing this.

I'm not sure if a dictionary would work (instead of a list).  I don't have any experience working with dictionaries, but I can't find any info on how to use a dictionary to create a featureclass even if I could figure them out.  Does anyone have any ideas?

In summary: how to I convert a csv with wkt geometry information into a feature class containing all fields?

import arcpy

# Set environments / workspace.  
arcpy.env.workspace = r"C:\Users\bhodge\Dropbox (New England Aquarium)\AIS_Projects\AISData\AISData.gdb"
arcpy.env.overwriteOutput = True

# Define Spatial Reference
wkt_sr = 'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'
sr = arcpy.SpatialReference()
sr.loadFromString(wkt_sr)

inputFile = r'C:\Users\bhodge\Projects\MMC_AIS\Data\TEST_OUTPUT_FILES\TestOutput.csv'

# Create an empty feature list
FeatureList = []
# iterate through table to pull geometries
fields = ['wkt_geom', 'id']
# array = arcpy.Array()
with arcpy.da.SearchCursor(inputFile, fields) as cur:
    for row in cur:
        # Name variables and assign values starting on first record of table
        wkt = row[0]
        id = row[1]
        tempWKT = arcpy.FromWKT(wkt, sr)
        FeatureList.append(tempWKT)
    else:
        pass
del cur

arcpy.CopyFeatures_management(FeatureList, r"C:\Users\bhodge\Dropbox (New England Aquarium)\AIS_Projects\AISData\AISData.gdb\TEST50")

 

Tags (3)
15 Replies
jblng
by
Occasional Contributor

Thanks, Josh! Quick follow-up question, I'm still wrapping my head around the difference between arcgis and arcpy. Is arcgis used to access the ArcGIS API, while arcpy is pulling from your local instance of Pro? Also, good to know about limitations of modifying a python env in Pro, saves me time knowing it's not really possible.

Thanks again! 

Jo

 

0 Kudos
Luis
by
Emerging Contributor

Hi Josh,

I'm trying to get this to work, but I'm getting the following error message:

AttributeError: 'str' object has no attribute 'loads'

I'm using the following code:

Python1.png

Here's a screenshot of the error:

Python.png

Any help would be greatly appreciated.

0 Kudos
by Anonymous User
Not applicable

Could be a long shot, but are you importing the GeoAssessor?

from arcgis.features import GeoAccessor, GeoSeriesAccessor

 

0 Kudos
Luis
by
Emerging Contributor

Hi Jeff, thanks for the suggestion.  There was actually an empty cell in the data that was causing a problem, but it's working now.  I appreciate it, though.

0 Kudos
Zartico-GIS
Occasional Contributor

@jcarlson This code has been a valuable find. Thank you very much for sharing.

I have it working, but I was unable to get a feature class to save into the provided .GDB. I can get an output for a .SHP though... Any idea why this would be? Code says it runs just fine with the feature class but when I check the destination it's empty.

0 Kudos
GeopixiDev
New Contributor

import arcpy
import csv

arcpy.env.overwriteOutput = True

# INPUTS---------------------------------------------#
input_csv = r"CSV FILE LOCATION"

# Output Geometry Information - type and the integer EPSG code that refers to the spatial reference.
geom_type = "MULTIPOLYGON" # This could also be POINT, POLYLINE, etc.
geom_sr = 4326 # you can Google your spatial reference name and "EPSG" to get this number

# Output Location and Name
out_gdb = r"YOUR.gdb"
out_name = "NAME_FC" # Leave if you want, this is the output feature class name

# Create a blank output FC using the provided geometry type and spatial reference.
out_fc = arcpy.management.CreateFeatureclass(out_path=out_gdb,
out_name=out_name,
geometry_type=geom_type,
spatial_reference=geom_sr, )

# Open CSV. Create Reader object.
with open(input_csv, "r", newline="") as csvfile:
csvreader = csv.reader(csvfile, delimiter=",")

# Create InsertCursor.
# For each row in CSV, attempt to convert WKT in column 1 to Esri Geometry object.
# All other columns are read, but ignored.
with arcpy.da.InsertCursor(out_fc, "SHAPE@") as icurs:
for wkt_geom, *other_columns in csvreader:

# Try to convert the WKT to a geom object.
try:
#print(f"CONVERTING WKT GEOM...\n{wkt_geom}")
geom_from_wkt = arcpy.FromWKT(wkt_geom, arcpy.SpatialReference(4326))

# Skip if conversion fails, could be bad formatting or a spreadsheet header.
except TypeError:
print(f"SKIPPING {wkt_geom}; IS THIS A HEADER?")
continue

# Attempt to write the Geometry object to the new feature class.
icurs.insertRow([geom_from_wkt])

 

This creates a "CLEAN" joinable FC that allows for many different use cases. You can design Toolbox to handle the params and allow users to change as desired.

0 Kudos