Select to view content in your preferred language

how to convert a feature layer to point

2130
6
Jump to solution
03-01-2022 07:20 AM
MVAC
by
Occasional Contributor

Hello,

I'm using jupyter notebooks (localhost, not in pro or AGOL), and I want to convert a feature layer to point. I've been trying to do it using arcpy.FeatureToPoint_management() but I'm having some issues:

parcels_id = 'the id'

# get layer

parcels = gis.content.get(parcels_id)

# get the required layer
parcels_layer = parcels.layers[0]

# variables
inFeatures = parcels_layer
outFeatureClass = i dont know how to address this part

# feature to point
arcpy.FeatureToPoint_management(inFeatures, outFeatureClass, "INSIDE")

For the outFeatureClass,  how can I do it to save it in a folder i have in my AGOL? is the inFeatures ok?

 

Thanks

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
jcarlson
MVP Esteemed Contributor

Here's a purely ArcGIS Python API way of doing this. Well, plus a little pandas.

  1. Query the layer
    1. Return as a dataframe
    2. Return centroid instead of geometry
  2. The centroid is just a JSON object, not a true shape, so we need to convert it.
    1. Export the centroid column to a dict
    2. Read the dict back into its own dataframe
    3. Convert the x/y columns to a true shape
  3. Export the spatial dataframe to a new layer in your portal
from arcgis import GIS, GeoAccessor
import pandas as pd

# connect to portal
gis = GIS('your url', 'username')

# get parcel layer
parcels = gis.content.get('parcels itemid').layers[0]

# set our spatial reference
sr = 4326 # or whatever your spatial reference is

# query features to dataframe
df = parcels.query(
    as_df = True,
    return_centroid = True,
    return_geometry = False,
    out_sr = sr
)

# convert centroid to dict
# ordinarily I don't like long single lines, but there's no point in assigning all the intermediate outputs to their own variables
sdf = GeoAccessor.from_xy(df.join(pd.DataFrame(df.loc[:, 'centroid'].to_dict()).T), 'x', 'y', sr=sr)

# drop the centroid columns
sdf.drop(columns=['x', 'y', 'centroid', 'objectid'], inplace=True)

# export to new feature class
sdf.spatial.to_featurelayer(
    title = 'My Awesome Parcel Centroids',
    gis = gis,
    tags = ['parcels', 'centroids', 'outputs'],
    folder = 'My Outputs',
    sanitize_columns = True,
    service_name = 'parcels_centroids'
)

You can just as easily export to other formats if you like.

Alternatively, you can use the GeoSeriesAccessor to take a spatial polygon column and derive the true_centroid of each, then assign the dataframe's shape attribute to that, but I tend to find the text → dict → x/y method performs a lot faster.

- Josh Carlson
Kendall County GIS

View solution in original post

6 Replies
ABishop
MVP Regular Contributor

Hello MVAC,

Not sure about using the feature to point to save directly to AGOL.  I have a feature that I create from a feature class in our versioned geodatabase with definition query applied and saved to a project in ArcGIS Pro.  I then upload it using the script below.  Hope this helps.

import arcpy, os, sys
from arcgis.gis import GIS
from datetime import datetime
import ctypes
ctypes.windll.kernel32.SetConsoleTitleW('AgUseParcelsFeatureServiceUpdate')

### Start setting variables
# Set the path to the project
prjPath = r"I:\users\abishop\PY\FeatureServiceUpdates\AgUseParcels\AgUseParcels.aprx"

# Update the following variables to match:
# Feature service/SD name in arcgis.com, user/password of the owner account
sd_fs_name = "Agricultural_Use_Parcels"
portal = "https://mcpafl.maps.arcgis.com/" # ArcGIS Online account
user = "abishop_MCPAFL"
password = "********"

# Set sharing options
shrOrg = True
shrEveryone = False
shrGroups = ""

### End setting variables

# Local paths to create temporary content
relPath = os.path.dirname(prjPath)
sddraft = os.path.join(relPath, "WebUpdate.sddraft")
sd = os.path.join(relPath, "WebUpdate.sd")

# Create a new SDDraft and stage to SD
print("Creating SD file")
arcpy.env.overwriteOutput = True
prj = arcpy.mp.ArcGISProject(prjPath)
mp = prj.listMaps()[0]
arcpy.mp.CreateWebLayerSDDraft(mp, sddraft, sd_fs_name, "MY_HOSTED_SERVICES", "FEATURE_ACCESS","", True, True, allow_exporting=True)
arcpy.StageService_server(sddraft, sd)

print("Connecting to {}".format(portal))
gis = GIS(portal, user, password)

# Find the SD, update it, publish /w overwrite and set sharing and metadata
print("Search for original SD on portal…")
sdItem = gis.content.search("{} AND owner:{}".format(sd_fs_name, user), item_type="Service Definition")[0]
print("Found SD: {}, ID: {} n Uploading and overwriting…".format(sdItem.title, sdItem.id))
sdItem.update(data=sd)
print("Overwriting existing feature service…")
fs = sdItem.publish(overwrite=True)

if shrOrg or shrEveryone or shrGroups:
 print("Setting sharing options…")
fs.share(org=shrOrg, everyone=shrEveryone, groups=shrGroups)

print("Finished updating: {} – ID: {}".format(fs.title, fs.id))

#provide input to stop script - uncomment input below if you need to see the script final output in the command window
input('Press ENTER to exit') 
Amanda Bishop, GISP
DanPatterson
MVP Esteemed Contributor

Moved this thread to the arcgis-api-for-python since it isn't python specific.

If you want to use the FeatureToPoint tool work local and upload the result.  Especially for shapefiles, you can only upload a zip of its parts


... sort of retired...
MVAC
by
Occasional Contributor

Would it be possible to do it on the notebook? I just checked and I don't need to save the point layer. I need this point layer to use arcgis.features.analysis.plan_routes() because I want to automate some stuff on workforce.

0 Kudos
DanPatterson
MVP Esteemed Contributor

You will have to wade through the help topic for it

arcgis.features.analysis module — plan_routes


... sort of retired...
jcarlson
MVP Esteemed Contributor

Here's a purely ArcGIS Python API way of doing this. Well, plus a little pandas.

  1. Query the layer
    1. Return as a dataframe
    2. Return centroid instead of geometry
  2. The centroid is just a JSON object, not a true shape, so we need to convert it.
    1. Export the centroid column to a dict
    2. Read the dict back into its own dataframe
    3. Convert the x/y columns to a true shape
  3. Export the spatial dataframe to a new layer in your portal
from arcgis import GIS, GeoAccessor
import pandas as pd

# connect to portal
gis = GIS('your url', 'username')

# get parcel layer
parcels = gis.content.get('parcels itemid').layers[0]

# set our spatial reference
sr = 4326 # or whatever your spatial reference is

# query features to dataframe
df = parcels.query(
    as_df = True,
    return_centroid = True,
    return_geometry = False,
    out_sr = sr
)

# convert centroid to dict
# ordinarily I don't like long single lines, but there's no point in assigning all the intermediate outputs to their own variables
sdf = GeoAccessor.from_xy(df.join(pd.DataFrame(df.loc[:, 'centroid'].to_dict()).T), 'x', 'y', sr=sr)

# drop the centroid columns
sdf.drop(columns=['x', 'y', 'centroid', 'objectid'], inplace=True)

# export to new feature class
sdf.spatial.to_featurelayer(
    title = 'My Awesome Parcel Centroids',
    gis = gis,
    tags = ['parcels', 'centroids', 'outputs'],
    folder = 'My Outputs',
    sanitize_columns = True,
    service_name = 'parcels_centroids'
)

You can just as easily export to other formats if you like.

Alternatively, you can use the GeoSeriesAccessor to take a spatial polygon column and derive the true_centroid of each, then assign the dataframe's shape attribute to that, but I tend to find the text → dict → x/y method performs a lot faster.

- Josh Carlson
Kendall County GIS
MVAC
by
Occasional Contributor

Thank you very much! 

Is there a way to overwrite the feature layer every time I run the code?