Esri / arcgis-python-api

Documentation and samples for ArcGIS API for Python
https://developers.arcgis.com/python/
Apache License 2.0
1.88k stars 1.1k forks source link

Convert DataFrames without a `SHAPE` column into `FeatureSets` #1485

Closed GeeFernando closed 1 year ago

GeeFernando commented 1 year ago

The following fix in ArcGIS API for Python 2.1 - "Fixes error when using sdf to create an empty dataframe from FeatureSet with empty SHAPE column and ArcPy not in environment" disables the ability to convert DataFrames without SHAPE columns into FeatureSets. Before upgrading to 2.1, I used this conversion (dataframes to featuresets) for editing hosted tables in ArcGIS Online.

Hosted Tables don't requires a SHAPE column. And with this version of the Python API it throws an error - if a DataFrame doesn't have a SHAPE column when converting to a FeatureSet.

I was just wondering what the best workaround would be for editing Hosted Tables in AGOL using DataFrames?

Cheers! - Gee Fernando

achapkowski commented 1 year ago

@GeeFernando can you post some reproducible code of this potential bug you are seeing so we can see what is going on?

GeeFernando commented 1 year ago

Hi @achapkowski, this works in ArcGIS API for Python 2.0xx but throws the following error in 2.1xx

import pandas as pd

# Relevant libraies to use 'Spatially Enabled Dataframes'
from arcgis.features import GeoAccessor, GeoSeriesAccessor

# Creating a dictionary with sample data
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emma'],
        'Age': [25, 32, 18, 47, 22],
        'Gender': ['Female', 'Male', 'Male', 'Male', 'Female'],
        'Country': ['USA', 'Canada', 'UK', 'Australia', 'USA']}

# Creating a DataFrame from the dictionary
df = pd.DataFrame(data)

# Convert df without a 'SHAPE' column into a featureset
df_fs = df.spatial.to_featureset()
df_fs
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/opt/conda/lib/python3.9/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   3360             try:
-> 3361                 return self._engine.get_loc(casted_key)
   3362             except KeyError as err:

/opt/conda/lib/python3.9/site-packages/pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

/opt/conda/lib/python3.9/site-packages/pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: None

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
/tmp/ipykernel_2350/3307508244.py in <cell line: 16>()
     14 
     15 # Convert df without a 'SHAPE' column into a featureset
---> 16 df_fs = df.spatial.to_featureset()
     17 df_fs

/opt/conda/lib/python3.9/site-packages/arcgis/features/geo/_accessor.py in to_featureset(self)
   3571         from arcgis.features import FeatureSet
   3572 
-> 3573         return FeatureSet.from_dict(self.__feature_set__)
   3574 
   3575     # ----------------------------------------------------------------------

/opt/conda/lib/python3.9/site-packages/arcgis/features/geo/_accessor.py in __feature_set__(self)
   3295             arcgis.geometry._types.Polygon: "esriGeometryPolygon",
   3296         }
-> 3297         if self.sr is None:
   3298             sr = {"wkid": 4326}
   3299         else:

/opt/conda/lib/python3.9/site-packages/arcgis/features/geo/_accessor.py in sr(self)
   3501         data = [
   3502             getattr(g, "spatialReference", None) or g["spatialReference"]
-> 3503             for g in self._data[self.name]
   3504             if g not in [None, np.NaN, np.nan, "", {}] and isinstance(g, dict)
   3505         ]

/opt/conda/lib/python3.9/site-packages/pandas/core/frame.py in __getitem__(self, key)
   3456             if self.columns.nlevels > 1:
   3457                 return self._getitem_multilevel(key)
-> 3458             indexer = self.columns.get_loc(key)
   3459             if is_integer(indexer):
   3460                 indexer = [indexer]

/opt/conda/lib/python3.9/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   3361                 return self._engine.get_loc(casted_key)
   3362             except KeyError as err:
-> 3363                 raise KeyError(key) from err
   3364 
   3365         if is_scalar(key) and isna(key) and not self.hasnans:

KeyError: None
nanaeaubry commented 1 year ago

Thanks for the sample, looking into it

achapkowski commented 1 year ago

This will be fixed in the next release.