2

I have a specified output path output_path, and a Pandas DataFrame df with two rows containing geoinformation (i.e. x and y coordinates):

#import relevant module
import pandas as pd

#define output path
output_path = r"C:/Users/123456/Documents/ArcGIS/"

## == create dataset == ##

# initialise data of lists.
data = {'X_coords':[75093, 103200], 'Y_coords':[432501, 433720]}
# Create DataFrame
df = pd.DataFrame(data)

which outputs:

    X_coords    Y_coords
0   75093       432501
1   103200      433720

My aim is to create a point feature dataset from a Pandas DataFrame, ideally via the ArcGIS function "XY Table To Point". However, if I try to apply this function in ArcPy:

arcpy.management.XYTableToPoint(df, output_path + "test.shp", "X_coords", "Y_coords")

I get an error:

RuntimeError                              Traceback (most recent call last)
In  [45]:
Line 1:     arcpy.management.XYTableToPoint(df, output_path + "test.shp", "X_coords", "Y_coords")

File C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\management.py, in XYTableToPoint:
Line 4644:  raise e

File C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\management.py, in XYTableToPoint:
Line 4641:  retval = convertArcObjectToPythonObject(gp.XYTableToPoint_management(*gp_fixargs((in_table, out_feature_class, x_field, y_field, z_field, coordinate_system), True)))

File C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\geoprocessing\_base.py, in <lambda>:
Line 512:   return lambda *args: val(*gp_fixargs(args, True))

RuntimeError: Object: Error in executing tool

Adding a Coordinate System as an argument results in a similar error.

Therefore, I have the following question: How can a Pandas DataFrame be converted to a point feature dataset, ideally via an ArcGIS function (e.g. XY Table To Point) in ArcPy?

3
  • Yes, I apply this in ArcGIS Pro Oct 4, 2022 at 9:17
  • How should you use the function da.InsertCursor on the Pandas DataFrame to create a point feature dataset then? Oct 4, 2022 at 9:44
  • 2
    You could use geopandas instead to create a spatial data frame and then save as a Shapefile. Oct 4, 2022 at 15:23

5 Answers 5

4

I do this using NumPyArrayToFeatureClass. Your output will need to be a feature class instead of a shapefile, and you'll need to convert your df to a np array.

array = df.to_records(index=False)
arcpy.da.NumPyArrayToFeatureClass(array, output_fc, ("X_coords", "Y_coords"))
1
  • 1
    You also need to define the crs arcpy.da.NumPyArrayToFeatureClass(array, output_fc, ("X_coords", "Y_coords"), "SpatialReference object") which you can call from the outlput fgb location or use the arcpy.SpatialReference(EPSD\WKID) to get it from it's corresponding ESPG or WKID number. Not to say this didn't help me, I just thought I would add how the crs is defined for the output. Additionally, mine worked when outputing to shape so...
    – MrKingsley
    Sep 28, 2023 at 16:34
3

Main answer:

From the arcpy's documentation:

The GeoAccessor class adds a spatial namespace that performs spatial operations on the given Pandas DataFrame. The GeoAccessor class includes visualization, spatial indexing, IO and dataset level properties.

So if we have a dataframe df containing a X and a Y column, we can simply use this new namespace:

from arcgis.features import GeoAccessor, GeoSeriesAccessor

# Convert a dataframe (df) to a spatial dataframe (sdf) with point geometrie
sdf = pd.DataFrame.spatial.from_xy(df=df,
x_column='X',
y_column='Y',
sr=4364)

# Save your feature class in a gdb (or in .shp,...)
sdf.spatial.to_featureclass(location=r'C:\MyDB.gdb\MyFeature', overwrite=True)

In addition:

The to_featureclass() function keep the data types of the dataframe, so if you load your dataframe from a .csv or an excel file, it can be useful to run:

df = df.convert_dtypes()

To get a more appropriate dtype for each of your column.

2

You can use da.InsertCursor:

import arcpy, os
import pandas as pd

output_path = r"C:\GIS\data\tempdata"
output_name= "points12345.shp"
sr = arcpy.SpatialReference(3006) #Create a spatial reference object. Change the code
arcpy.CreateFeatureclass_management(out_path=output_path, out_name=output_name, geometry_type="POINT", spatial_reference=sr) #Create an empty fc

data = {'X_coords':[398905, 492561], 'Y_coords':[6340963, 6526362]}
df = pd.DataFrame(data)

cursor = arcpy.da.InsertCursor(os.path.join(output_path, output_name), ['SHAPE@XY'])
for row in zip(df['X_coords'], df['Y_coords']): #For each row. row will be a tuple, like (492561, 6526362)
    cursor.insertRow([row]) #Create a feature
del cursor

enter image description here

I agree with the comment, it would be simple to use geopandas for this.

2

Another alternative is to use a Spatially Enabled DataFrame. Creating the geometry is a little cumbersome, but you can save directly to a table or feature class. Here is one example but there are different approaches You could also write a function to create the geometry or use apply with the dataframe.

import pandas as pd

from arcgis.features import GeoAccessor, GeoSeriesAccessor
from arcgis.geometry import Point


shapes = [
    Point({"x":75093,"y":432501,"spatialReference":{"wkid":3857}}),
    Point({"x":103200,"y":433720,"spatialReference":{"wkid":3857}}),
]

data = {"SHAPE":shapes,"ids":[1,2]}
# Create DataFrame
df = pd.DataFrame(data)

sdf = pd.DataFrame.spatial.from_df(df,geometry_column="SHAPE")

out_path = r"c:/temp/ExampleTablePoints.shp"
sdf.spatial.to_featureclass(out_path)

More info: https://developers.arcgis.com/python/guide/introduction-to-the-spatially-enabled-dataframe/

0

I found a workaround by first converting it to a csv file, which can then be used as the "in_table" argument in the "XY Table To Point" function:

# step 1. convert to csv
df.to_csv(output_path + "df.csv")

# step 2. drag df.csv into table of contents

# step 3. use converted csv file as input for function XY Table To Point (Coordinate System = RD New)
arcpy.management.XYTableToPoint("df.csv", output_path + "df_xy.shp", "X_coords", "Y_coords", None, 'PROJCS["RD_New",GEOGCS["GCS_Amersfoort",DATUM["D_Amersfoort",SPHEROID["Bessel_1841",6377397.155,299.1528128]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Double_Stereographic"],PARAMETER["False_Easting",155000.0],PARAMETER["False_Northing",463000.0],PARAMETER["Central_Meridian",5.38763888888889],PARAMETER["Scale_Factor",0.9999079],PARAMETER["Latitude_Of_Origin",52.15616055555555],UNIT["Meter",1.0]];-30515500 -30279500 10000;-100000 10000;-100000 10000;0.001;0.001;0.001;IsHighPrecision')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.