4

I'm working to develop a tool that converts JSON data pulled from an API into a feature class to be stored in an ESRI file geodatabase. I'm currently testing the functionality in a Jupyter notebook within an ArcGIS Pro project but my goal is to eventually convert my script into a geoprocessing tool that can be used by non-developer users. However, I've gotten stuck in the prototype phase and cannot figure out if I am running into a bug or if there is an issue with my code.

Here is my code:

import requests
import arcpy
from arcgis.features import GeoAccessor, GeoSeriesAccessor
import pandas as pd

# pull public geojson data from socrata

r = requests.get('https://data.bayareametro.gov/resource/ufzj-38uk.json')
j = r.json()
df = pd.DataFrame.from_dict(j)

# Convert to Spatially Enabled Pandas Dataframe

sedf = pd.DataFrame.spatial.from_df(df, geometry_column='shape')

# Export Spatially Enabled Pandas Dataframe to FGDB Feature Class

sedf.spatial.to_featureclass(location='equity_priority_areas_2020')

This is the error message I received:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
In  [22]:
Line 5:     sanitize_columns=True)

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\features\geo\_accessor.py, in to_featureclass:
Line 2388:  has_m=has_m,

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\features\geo\_io\fileops.py, in to_featureclass:
Line 853:   df.columns = original_columns

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\pandas\core\generic.py, in __setattr__:
Line 5478:  return object.__setattr__(self, name, value)

File pandas\_libs\properties.pyx, in pandas._libs.properties.AxisProperty.__set__:
Line 66:    

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\pandas\core\generic.py, in _set_axis:
Line 670:   self._mgr.set_axis(axis, labels)

File C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\pandas\core\internals\managers.py, in set_axis:
Line 221:   f"Length mismatch: Expected axis has {old_len} elements, new "

ValueError: Length mismatch: Expected axis has 42 elements, new values have 41 elements
---------------------------------------------------------------------------

Here is what I tried to resolve the issue:

I reviewed the GeoAccessor class method to_featureclass API reference and tried to set the path to the File Geodatabase explicitly as well as provide explicit values for the has_z, haz_m, and sanitize_columns parameters as shown below and got the same error message.

sedf.spatial.to_featureclass(location='Z:\Documents\ArcGIS\Projects\Socrata_to_ArcGIS\Socrata_to_ArcGIS.gdb\equity_priority_areas_2020', 
                             overwrite=True, 
                             has_z=False, 
                             has_m=False, 
                             sanitize_columns=True)

I seem to always run into issues when trying to perform seemingly basic things with these spatially enabled dataframes.

2
  • You could use the arcpy.JSONToFeatures_conversion tool pro.arcgis.com/en/pro-app/latest/tool-reference/conversion/… and remove the need for pandas and GeoAccessor Apr 7, 2022 at 13:35
  • 1
    @Clubdebambos thank you for your comment. I though of trying to leverage that tool but I think that would require a download of the json data first before conversion. I believe it does not support data streams if I'm not mistaken. Or in other words, data pulled from an API. Apr 8, 2022 at 15:48

1 Answer 1

1

I had this issue after updating ArcGIS Pro and arcpy to v2.9. Basically if the SEDF did not have a geometry column named "SHAPE" (all caps) then the ValueError: Length mismatch: Expected axis has 42 elements, new values have 41 elements error was thrown.

Try renaming your geometry column from "shape" to "SHAPE".

Implementing something like this into your workflow should solve permanently.

if geo_column != 'SHAPE':
    df.rename(columns={geo_column: "SHAPE"}, inplace=True)
sedf = GeoAccessor.from_df(
  df=df,
  sr=sr, 
  geometry_column="SHAPE",    )

Your Answer

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

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