In short, yes, you're not quite using the spatially enabled dataframe correctly. Accomplishing your goal is quite simple, but you have to create an intermediate GeoSeriesAccessor object. This class allows you to perform operations like area, extent, etc., on an entire series of shapes, which avoids needing to iterate over your dataframe. You can also use the project_as method to get those outputs into degrees.
# Add this to your import statements
from arcgis.features import GeoSeriesAccessor
# Grab the layer directly, without as many intermediate outputs
# Using content.get avoids potentially inconsistent results from a search
lyr = gis.content.get('itemID').layers[0]
# Query features directly to a dataframe
df = lyr.query(where = 'AreaSqFeet IS NULL', as_df=True)
# Create GeoSeriesAccessor
gsa = GeoSeriesAccessor(df['SHAPE'])
# Use GSA to calculate fields
df['area_field'] = gsa.area
df['centroid_dd'] = gsa.centroid
df['extent_field'] = gsa.extent
Mind you, centroid and extent return tuples, so you may need to do some extra work to reformat that as needed for your fields. It might look something like this:
new_col_list = ['xmin','ymin','xmax','ymax']
for n,col in enumerate(new_col_list):
df[col] = df['extent'].apply(lambda extent: extent[n])
df.drop(columns='extent', inplace=True)
If you have trouble projecting your dataframe / geoseriesaccessor, as I sometimes do, note that you can also specify a different spatial reference to be output from your query itself, by specifying out_sr=* as a parameter.
EDIT: I forgot to mention, when you're done, you can submit your edits in one go, rather than as part of an interative process. edit_features takes a featureset for the updates parameter, and you can convert your dataframe directly to a featureset once you've performed your calculations.
lyr.edit_features(updates = df.spatial.to_featureset())
- Josh Carlson
Kendall County GIS