Extract Coordinates from SEDF

3611
8
06-13-2020 12:14 PM
LarrySpear
New Contributor III

Extracting Point Coordinates from a SEDF: Using the ArcGIS API for Python and a Spatially Enabled Data Frame (SEDF) I would like to know if there is an easy way similar to using GeoPandas to extract  the x and y coordinates of points (census tract centroids) and assign them to new items/variables? For instance in GeoPandas:

   df_tract['XC'] = df_tract.geometry.x  and  df_tract['YC'] = df_tract.geometry.y

   This will produce an Attribute Error:  'DataFrame' object has no attribute 'geometry' 

I know the SEDF stores geometry as a SHAPE dictionary and have tried various direct ways to get these coordinated short of iterating through the distionary such as:

df_tract['XC'] = df_tract.get("x")  and  df_tract['YC'] = df_tract.get("y")

   No error this way but resulting values are None

I am slowly becoming more familar with using Python so any suggestions would be greatly appreciated.

8 Replies
DanPatterson
MVP Esteemed Contributor

There are several ways to get the centroid and hence, the X and Y coordinates

SpatialDataFrame.centroid 

GeoAccessor.centroid 

Other options can be found looking in the api's help


... sort of retired...
LarrySpear
New Contributor III

Hi Dan, thanks for the suggestions about how to calculate centroids from a SEDF. However, my problem is somewhat different. The SEDF was created from an existing point-based feature class that are (already consists of) centroids or mostly required equivalents (New Mexico census tract post office locations in a populated place and centroids of tracts with no P.O.). These are being used for calculating a healthcare related gravity model (access to primary care physicians, etc.). This gravity model has already been implemented using Python - GeoPandas (Jupyter Notebook) R, and originally with SAS. I was just investigating if it could now be implemented using the ArcGIS API and the new SEDF within an ArcGIS Pro Notebook. It was very easy to extract the existing point (centroid, etc.) coordinates from the geometry contained in a GeoPandas data frame. But, it does not seem to be that straight forward from a SEDF SHAPE. Perhaps this method could be implemented in a subsequent SEDF release to work similar to how easy it is with GeoPandas. I could always just use an ArcGIS Desktop or Pro to add the coordinates (from the geometry tokens SHAPE@X and SHAPE@Y) to the feature class first and then create the SEDF for later use. Still open to learning a more direct way if possible?

Larry Spear M.A., GISP Phone: (505) 508-5942

Sr. Research Scientist (Ret.) Cell: (505) 401-5756

Division of Government Research Email: lspear@unm.edu<mailto:lspear@unm.edu>

Non-degree Graduate Student URL: http://www.unm.edu/~lspear

University of New Mexico

Albuquerque, New Mexico 87131

0 Kudos
DanPatterson
MVP Esteemed Contributor

I use numpy (which pandas largely depends on) for all my shape and attribute work.  Point geometry is easy with FeatureClassToNumPyArray.  Attributes are a snap with TableToNumPyArray.  The attribute column extraction is the same  someArray['SomeField'].  

I have many, many blog posts on numpy's use in GIS 

Py... blog 

They are ones I wrote in my previous incarnation as a faculty member before I retired.

My new incarnation posts ArcGIS Pro and numpy tools at

 


... sort of retired...
0 Kudos
LarrySpear
New Contributor III

Thanks again! I used FeatureClassToNumPyArray to get the point coordinates then created a pandas data frame from the numpy array and merged it with the SEDF to create a new SEDF and got what I wanted. Not as direct as in GeoPandas but it will work.

  1. Get the NM census tract with provider Feature Class (CT 2002)

  2. Note: Projection already EPSG: 26913 (NAD83 / UTM zone 13N)​

  3. Also Create a Spatially Enabled Data Frame (SEDF) and Numeric GEOIDN​

ct_tract_pt_lyr = "ct2002exp_t1"​

nmctpp = pd.DataFrame.spatial.from_featureclass(ct_tract_pt_lyr)​

nmctpp['GEOIDN'] = pd.to_numeric(nmctpp['GEOID'])

  1. Extract the point (place and centroid) coordinates

ct_coords_array = arcpy.da.FeatureClassToNumPyArray(ct_tract_pt_lyr, (["OID@", "SHAPE@X", "SHAPE@Y"]))

  1. Create a Pandas DataFrame from NumPy Array

ct_coords_df = pd.DataFrame(data=ct_coords_array, index=None, columns=None)​

ct_coords_df['OBJECTID'] = ct_coords_df['OID@']

  1. Merge the coordinates on to a new SEDF

nmctppc = nmctpp.merge(ct_coords_df, on = 'OBJECTID')

0 Kudos
wwnde
by
Occasional Contributor

@LarrySpear , @DanPatterson

Saw this a tad late but here is another way to go about it.

ArcGIS API for python has elaborate methods to extract centroids. Refer to this  document

If you have your content on AGOL

 

 

from arcgis.gis import GIS
import arcgis
from arcgis import features
from arcgis.features import GeoAccessor, GeoSeriesAccessor, FeatureLayer
from arcgis import geometry 
from arcgis.features.find_locations import find_centroids

#sign in portal
gis = GIS("https://url.arcgis.com", "UserName", "Password")

#Feature Service
item=gis.content.get('Feature_Service_ID')
l=item.layers[0]

#Generate Centroids. PLEASE NOTE THEY WILL BE PUBLISHED ON PORTAL
poly_to_point = find_centroids(l, output_name="Centroids")

 

 

You can then generate and tabulate the geometry

 


 

0 Kudos
Kristen
New Contributor II

 

# for points
sdf['YCoord'] = sdf['SHAPE'].apply(lambda shape: shape.y)
sdf['XCoord'] = sdf['SHAPE'].apply(lambda shape: shape.x)

# for polygons
sdf['YCoord'] = sdf['SHAPE'].apply(lambda shape: shape.centroid[1])
sdf['XCoord'] = sdf['SHAPE'].apply(lambda shape: shape.centroid[0])

 

wwnde
by
Occasional Contributor

A nother way to do it would be;

 sdf=sdf.assign(longitude=sdf.SHAPE.astype(str).apply(lambda x: Point(x)\
            .coordinates()).str[0],latitude=sdf.SHAPE.astype(str).\
                apply(lambda x: Point(x).coordinates()).str[1])
0 Kudos
by Anonymous User
Not applicable

One solution i could think of to achieve this with ArcGIS Python API.

1. export the sedf into FeatureSet

2. get features from FeatureSet 

3. get geometry from the feature

4. get centroid with the geometry's centroid property

0 Kudos