Unable to write a featureSet as shapefile (via sdf)

496
2
Jump to solution
07-03-2019 10:23 AM
GretaVega
New Contributor

Hi.

I would like to write a shapefile from a featureSet created after .query()

As you can see in the picture I have the featureSet, I cast it as a panda.DataFrame but then supposedly I should be able to use the method  to_featureclass following the instructions from here: https://developers.arcgis.com/python/guide/introduction-to-the-spatial-dataframe/#Saving-Spatial-Dat...

But my object does not have this method. I am really confused why it doesn't. 

The only question similar to mine that I have found is this one: https://community.esri.com/message/824163-cant-export-spatialdataframe-to-shapefile But I am afraid it didn't help me.

Many thanks for any input. 

Greta

0 Kudos
1 Solution

Accepted Solutions
EarlMedina1
Occasional Contributor III

Hi Greta,

You may have already figured this out, but it looks like you missed 'spatial' - it should read:

'xx_sdf.spatial.to_featureclass'

I see this working with the below example script using version 1.6.2 of the API. This particular example maintains the source projection:

from arcgis import GIS
from arcgis.features import FeatureLayerCollection, GeoAccessor, GeoSeriesAccessor
from arcgis.geometry import SpatialReference
import pandas as pd


def search_item(conn, item_name, item_type, flc=False):
search_results = conn.content.search(item_name, item_type=item_type)
proper_index = [i for i, s in enumerate(search_results) if '"' + item_name + '"' in str(s)]
found_item = search_results[proper_index[0]]
if flc == False:
get_item = conn.content.get(found_item.id)
return get_item
if flc == True:
flc = FeatureLayerCollection.fromitem(found_item)
return flc

def main():
conn = GIS("https://www.arcgis.com", "Username", "Password")
flc = search_item(conn, "Name_of_Feature_Layer", "Feature Layer", True)
layer = flc.layers[0]
epsg_code = layer.properties['extent']['spatialReference']['latestWkid']
feature_set = layer.query()
sdf = feature_set.sdf
srs = SpatialReference({"wkid":epsg_code})
sdf.spatial.project(srs)
sdf.spatial.to_featureclass(location="/home/test.shp")

if __name__ == '__main__':
main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

An alternative approach would be to use the fiona library instead of sdf to write the shapefile. The equivalent workflow is something like this:

  1. Get the EPSG code from the Spatial Reference in the Feature Layer properties (obtained as shown above).
  2. Run to_geojson on the Feature Set.
  3. Load and open the Feature Set geojson with fiona.ogrext.buffer_to_virtual_file
  4. Write to a new file using the Esri Shapefile driver:
    • Here, I set the optional crs parameter equal to the result of Fiona's from_epsg with the EPSG code from before.

Hope this helps!

-Earl

View solution in original post

2 Replies
EarlMedina1
Occasional Contributor III

Hi Greta,

You may have already figured this out, but it looks like you missed 'spatial' - it should read:

'xx_sdf.spatial.to_featureclass'

I see this working with the below example script using version 1.6.2 of the API. This particular example maintains the source projection:

from arcgis import GIS
from arcgis.features import FeatureLayerCollection, GeoAccessor, GeoSeriesAccessor
from arcgis.geometry import SpatialReference
import pandas as pd


def search_item(conn, item_name, item_type, flc=False):
search_results = conn.content.search(item_name, item_type=item_type)
proper_index = [i for i, s in enumerate(search_results) if '"' + item_name + '"' in str(s)]
found_item = search_results[proper_index[0]]
if flc == False:
get_item = conn.content.get(found_item.id)
return get_item
if flc == True:
flc = FeatureLayerCollection.fromitem(found_item)
return flc

def main():
conn = GIS("https://www.arcgis.com", "Username", "Password")
flc = search_item(conn, "Name_of_Feature_Layer", "Feature Layer", True)
layer = flc.layers[0]
epsg_code = layer.properties['extent']['spatialReference']['latestWkid']
feature_set = layer.query()
sdf = feature_set.sdf
srs = SpatialReference({"wkid":epsg_code})
sdf.spatial.project(srs)
sdf.spatial.to_featureclass(location="/home/test.shp")

if __name__ == '__main__':
main()‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

An alternative approach would be to use the fiona library instead of sdf to write the shapefile. The equivalent workflow is something like this:

  1. Get the EPSG code from the Spatial Reference in the Feature Layer properties (obtained as shown above).
  2. Run to_geojson on the Feature Set.
  3. Load and open the Feature Set geojson with fiona.ogrext.buffer_to_virtual_file
  4. Write to a new file using the Esri Shapefile driver:
    • Here, I set the optional crs parameter equal to the result of Fiona's from_epsg with the EPSG code from before.

Hope this helps!

-Earl

View solution in original post

GretaVega
New Contributor

Hi Earl,

Apologies for my confusion and thank you so much for your detailed answer it is super useful!

I have managed to export the data.

Cheers.

Greta

0 Kudos