The ArcGIS API for Python makes programmatic editing of features a breeze. In this guide, we'll cover the edit_features()
method on the FeatureLayer
object, which is a great way to add, update and delete features from a point feature layer. For more about the function, refer to the reference page for the FeatureLayer class and scroll down to edit_features()
.
Let's start by grabbing our feature layer.
# connect to GIS
from arcgis.gis import GIS
from IPython.display import display
gis = GIS(profile="your_online_profile")
# search for the feature layer named Ports along west coast
portal_item = gis.content.get('e0dae2efe40a414a9700bee3a35c846b')
portal_item
# access the item's feature layers
ports_layer = portal_item.layers[0]
ports_layer
<FeatureLayer url:"https://services7.arcgis.com/JEwYeAy2cc8qOe3o/arcgis/rest/services/Ports_along_the_US_West_Coast/FeatureServer/0">
Query the features
Let's query the features in the layer to see what we're working with.
# query all the features and display it on a map
# an empty query string will return all features or the first 1000, whichever is smaller
ports_fset = ports_layer.query()
The sdf
property of FeatureSet
class is a powerful way to visualize all the features as a pandas dataframe table. This creates a Spatially Enabled DataFrame, which is a Pandas DataFrame with extended spatial capabilities. More on the SeDF can be found here.
ports_fset.sdf
objectid | country | globalid | harborsize | label_position | latitude | longitude | port_name | short_form | geometry_x | geometry_y | globalid_1 | SHAPE | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | US | {14FB62C9-1CEA-4F12-ACA4-14BB72F042BF} | L | SW | 37.816667 | -122.416667 | SAN FRANCISCO | SFFO | -13627360 | 4553559 | {9D3F40A8-C4C5-4C59-A82C-3C3B19373671} | {"x": -13627361.035, "y": 4553559.283399999, "... |
1 | 2 | US | {6EE30C76-399D-42F5-B6ED-403C94DFFCD4} | S | SW | 37.783333 | -122.266667 | ALAMEDA | NGZ | -13610660 | 4548863 | {6FD08053-6335-474A-B976-6D42A9D1D528} | {"x": -13610663.1114, "y": 4548863.0858, "spat... |
2 | 3 | US | {A6A21CC3-DE52-4B8A-A5B2-1CAA726E7F02} | L | SW | 37.816667 | -122.333333 | OAKLAND | OAK | -13618080 | 45535590 | {E44E1348-822A-413B-9FFE-7C49CF527027} | {"x": -13618084.3366, "y": 4553559.283399999, ... |
3 | 4 | US | {265AD7A6-4F59-4181-88DE-194F23F64E92} | S | SW | 37.916667 | -122.366667 | POINT RICHMOND | RIC | -13621800 | 4567660 | {030877E0-580F-46D2-A2A7-66ECDD6B9093} | {"x": -13621795.0605, "y": 4567660.334200002, ... |
4 | 5 | US | {B15D545F-83DD-4D3E-9051-6D9F290A8E9E} | S | SW | 38.100000 | -122.266667 | MARE ISLAND | None | -13610660 | 4593562 | {20B9B1A1-E243-4C82-8158-CA11A93B38C8} | {"x": -13610663.1114, "y": 4593562.1065, "spat... |
5 | 6 | US | {A97E8B59-1E25-416E-9206-4B59A869E2F4} | S | SW | 38.083333 | -122.250000 | SOUTH VALLEJO | None | -13608810 | 4591205 | {A18751ED-E493-44C3-A684-602488346594} | {"x": -13608807.749499999, "y": 4591204.668700... |
6 | 7 | US | {8EB57C5B-100B-4C50-B6B1-4D6B9B1C7545} | S | SW | 37.950000 | -121.300000 | STOCKTON | SCK | -13503050 | 4572365 | {A2688CB5-CDFB-4A8A-B76F-F0AB0D1FCAAC} | {"x": -13503054.233199999, "y": 4572364.8957, ... |
7 | 8 | US | {3B7B126E-0B60-49AF-89AA-4AC05402CFEA} | S | SW | 38.583333 | -121.500000 | SACRAMENTO | SMF | -13525320 | 4662162 | {A86D6850-70B8-43B6-BB66-73B5E4D46C48} | {"x": -13525318.1314, "y": 4662162.127899997, ... |
8 | 9 | US | {20378B4B-3E9E-47D2-AF42-4F0A31D5CA66} | S | SW | 40.800000 | -124.183333 | EUREKA | ACV | -13824030 | 4982886 | {A01048CF-CE39-44FE-AF40-B3F792D2DE9E} | {"x": -13824025.3946, "y": 4982886.316600002, ... |
9 | 10 | US | {782C11E0-B02D-45AB-8BAD-97C1B5817812} | M | SW | 43.400000 | -124.283333 | EMPIRE | None | -13835160 | 5373055 | {7B19D43F-DD50-48C6-BBD3-01930B3605A4} | {"x": -13835157.3437, "y": 5373055.471900001, ... |
10 | 11 | US | {888593DC-D385-4A7C-A1F0-C9D46AB91353} | S | SW | 43.366667 | -124.216667 | COOS BAY | None | -13827740 | 5367950 | {B63F5915-F764-46A1-BA81-1209BDEA3438} | {"x": -13827736.1185, "y": 5367949.881800003, ... |
11 | 12 | US | {A04935D7-314D-43D3-AA39-99E91FE93BD5} | M | SW | 32.716667 | -117.183333 | SAN DIEGO | SAN | -13044790 | 3857756 | {A325CED6-0C85-46D3-9524-B0E253ECFBFA} | {"x": -13044788.958999999, "y": 3857756.351199... |
12 | 13 | US | {45CCFAFA-CE13-4EEE-907A-5C53A486C434} | M | SW | 33.766667 | -118.183333 | LONG BEACH | LGH | -13156110 | 3997514 | {A904E129-30BE-41C5-B0F6-ABB5C8521FE7} | {"x": -13156108.4498, "y": 3997513.9714, "spat... |
13 | 14 | US | {ECA58B5E-ADBB-4392-A6F2-1F5476E69375} | S | SW | 36.616667 | -121.883333 | MONTEREY | MRY | -13567990 | 4385809 | {63CEB887-33E7-46AF-8710-9DDD4E2F3C19} | {"x": -13567990.5657, "y": 4385808.953900002, ... |
14 | 15 | US | {9B472045-E648-4371-906A-FCC35A7CB0B1} | L | SW | 45.516667 | -122.666667 | PORTLAND | None | -13655190 | 5703230 | {9A803AB5-5EB9-4BA2-AA17-CB708E3CD92C} | {"x": -13655190.9077, "y": 5703230.203000002, ... |
15 | 16 | US | {B8AC37F8-5AA6-4D27-A401-7B35A8E4B9D3} | S | SW | 21.950000 | -159.350000 | NAWILIWILI BAY | None | -17738760 | 2505523 | {0C4B2263-59C7-463B-AF9C-284C07B8DFB0} | {"x": -17738760.8579, "y": 2505523.1952, "spat... |
16 | 17 | US | {6D718925-1CF2-4A45-9E3D-B4FBE215BA71} | S | SW | 21.900000 | -159.583333 | PORT ALLEN | None | -17764740 | 2499523 | {59634BC9-1CDE-4F56-84F1-0C29C6787169} | {"x": -17764735.3687, "y": 2499523.2661000006,... |
17 | 18 | US | {50ECBCE3-137E-45BF-A42E-F0D423434067} | M | SW | 21.300000 | -157.866667 | HONOLULU | HNL | -17573640 | 2427687 | {A9E9A7A1-4D5E-42C7-9F53-D09C3E04D441} | {"x": -17573636.9837, "y": 2427686.5436000004,... |
18 | 19 | US | {9168C51F-28FF-4885-AFD5-18A1607E3808} | S | SW | 20.033333 | -155.833333 | KAWAIHAE | None | -17347290 | 2276980 | {7E86F7D7-4E2E-43BC-893A-09D0F1E78092} | {"x": -17347287.2782, "y": 2276980.0967999995,... |
19 | 20 | US | {A2A35C01-C1D4-4FD0-B74E-424E1A9DE20F} | M | SW | 19.733333 | -155.066667 | HILO | ITO | -17261940 | 2241467 | {1F6FCB1A-7F2D-4DC9-9571-05E685D2A66A} | {"x": -17261942.4095, "y": 2241467.1730999984,... |
20 | 21 | US | {BC904585-28E5-4995-9F6F-BCBDEE4D00C2} | M | SW | 45.633333 | -122.683333 | VANCOUVER | None | -13657050 | 5721784 | {57CDFEA4-FA11-41C4-8A69-943C5114CDC0} | {"x": -13657046.1584, "y": 5721784.0173999965,... |
21 | 22 | US | {8AFA0145-A107-4031-B05B-1D09550E9D88} | S | SW | 34.055600 | -117.182000 | REDLANDS | None | -13044640 | 4036270 | {0CD089EE-1465-4055-BD3B-6566759D2F1F} | {"x": -13044640.5701, "y": 4036270.1933000013,... |
Check if the layer can be edited
To enable a feature layer to be edited, the edit
capability needs to be turned on for the item. This can be verified by accessing the capabilities
property on the FeatureLayer
object:
ports_layer.properties.capabilities
'Query,Sync,Extract,Editing'
Editing features
Updating features
From the dataframe above, we notice the short_form field of San Francisco port has a typo. We can update this by calling the edit_features()
method on the ports_flayer
FeatureLayer
object. The edit_features()
method accepts a Feature
object with correct parameters set.
ports_features = ports_fset.features
# select San Francisco feature
sfo_feature = [f for f in ports_features if f.attributes['port_name']=='SAN FRANCISCO'][0]
sfo_feature.attributes
{'objectid': 1, 'country': 'US', 'globalid': '{14FB62C9-1CEA-4F12-ACA4-14BB72F042BF}', 'harborsize': 'L', 'label_position': 'SW', 'latitude': 37.816667, 'longitude': -122.416667, 'port_name': 'SAN FRANCISCO', 'short_form': 'SFFO', 'geometry_x': -13627360, 'geometry_y': 4553559, 'globalid_1': '{9D3F40A8-C4C5-4C59-A82C-3C3B19373671}', 'SHAPE': {'x': -13627361.035, 'y': 4553559.283399999, 'spatialReference': {'wkid': 102100, 'latestWkid': 3857}}}
As we can see above, the short_form
attribute should be changed to SFO
. Let us edit that and store it as a new Feature
object.
sfo_edit = sfo_feature
sfo_edit.attributes['short_form'] = 'SFO'
display(sfo_edit)
{"geometry": {"x": -13627361.035, "y": 4553559.283399999, "spatialReference": {"wkid": 102100, "latestWkid": 3857}}, "attributes": {"objectid": 1, "country": "US", "globalid": "{14FB62C9-1CEA-4F12-ACA4-14BB72F042BF}", "harborsize": "L", "label_position": "SW", "latitude": 37.816667, "longitude": -122.416667, "port_name": "SAN FRANCISCO", "short_form": "SFO", "geometry_x": -13627360, "geometry_y": 4553559, "globalid_1": "{9D3F40A8-C4C5-4C59-A82C-3C3B19373671}", "SHAPE": {"x": -13627361.035, "y": 4553559.283399999, "spatialReference": {"wkid": 102100, "latestWkid": 3857}}}}
Now, we'll send this feature object to the edit_features()
method and edit the original feature layer.
update_result = ports_flayer.edit_features(updates=[sfo_edit])
update_result
{'addResults': [], 'updateResults': [{'objectId': 1, 'globalId': '{9D3F40A8-C4C5-4C59-A82C-3C3B19373671}', 'success': True}], 'deleteResults': [], 'attachments': {'addResults': [], 'updateResults': [], 'deleteResults': []}}
Adding features
From the data frame, we also notice that 'Los Angeles', an important port, is missing. We can add this to the original layer by calling the edit_features()
method and passing a dictionary representation of the feature with the adds
parameter.
# construct a Feature object for Los Angeles.
la_dict = {"attributes":
{"latitude": 33.75,
"longitude": -118.25,
"country": "US",
"harborsize": "L",
"label_position": "SW",
"port_name": "LOS ANGELES",
"short_form": "LAX"},
"geometry":
{"x": -13044788.958999995, "y": 3857756.351200014}}
add_result = ports_flayer.edit_features(adds = [la_dict])
add_result
{'addResults': [{'objectId': 23, 'globalId': '{F5FCFF4C-ED2F-4C72-80EF-B414EF4C8C5B}', 'success': True}], 'updateResults': [], 'deleteResults': [], 'attachments': {'addResults': [], 'updateResults': [], 'deleteResults': []}}
Deleting features
From the DataFrame, we also notice that 'Redlands', a landlocked city, is wrongly included as a port. We can remove it by calling the edit_features()
method and passing the object id of the unwanted feature to the deletes
parameter.
# find object id for Redlands
Redlands_feature = [f for f in ports_features if f.attributes['port_name'] == 'REDLANDS'][0]
Redlands_objid = Redlands_feature.get_value('objectid')
Redlands_objid
22
type(Redlands_objid)
int
# pass the object id as a string to the delete parameter
delete_result = ports_flayer.edit_features(deletes=str(Redlands_objid))
delete_result
{'addResults': [], 'updateResults': [], 'deleteResults': [{'objectId': 22, 'globalId': None, 'success': True}], 'attachments': {'addResults': [], 'updateResults': [], 'deleteResults': []}}
Check results of edit operations
We have successfully added, removed and edited features. Let's query the layer once again and display the results as a DataFrame to verify them.
ports_fset_edited = ports_flayer.query()
ports_fset_edited.sdf
objectid | country | globalid | harborsize | label_position | latitude | longitude | port_name | short_form | geometry_x | geometry_y | globalid_1 | SHAPE | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | US | {14FB62C9-1CEA-4F12-ACA4-14BB72F042BF} | L | SW | 37.816667 | -122.416667 | SAN FRANCISCO | SFO | -13627360.0 | 4553559.0 | {9D3F40A8-C4C5-4C59-A82C-3C3B19373671} | {"x": -13627361.035, "y": 4553559.283399999, "... |
1 | 2 | US | {6EE30C76-399D-42F5-B6ED-403C94DFFCD4} | S | SW | 37.783333 | -122.266667 | ALAMEDA | NGZ | -13610660.0 | 4548863.0 | {6FD08053-6335-474A-B976-6D42A9D1D528} | {"x": -13610663.1114, "y": 4548863.0858, "spat... |
2 | 3 | US | {A6A21CC3-DE52-4B8A-A5B2-1CAA726E7F02} | L | SW | 37.816667 | -122.333333 | OAKLAND | OAK | -13618080.0 | 45535590.0 | {E44E1348-822A-413B-9FFE-7C49CF527027} | {"x": -13618084.3366, "y": 4553559.283399999, ... |
3 | 4 | US | {265AD7A6-4F59-4181-88DE-194F23F64E92} | S | SW | 37.916667 | -122.366667 | POINT RICHMOND | RIC | -13621800.0 | 4567660.0 | {030877E0-580F-46D2-A2A7-66ECDD6B9093} | {"x": -13621795.0605, "y": 4567660.334200002, ... |
4 | 5 | US | {B15D545F-83DD-4D3E-9051-6D9F290A8E9E} | S | SW | 38.100000 | -122.266667 | MARE ISLAND | None | -13610660.0 | 4593562.0 | {20B9B1A1-E243-4C82-8158-CA11A93B38C8} | {"x": -13610663.1114, "y": 4593562.1065, "spat... |
5 | 6 | US | {A97E8B59-1E25-416E-9206-4B59A869E2F4} | S | SW | 38.083333 | -122.250000 | SOUTH VALLEJO | None | -13608810.0 | 4591205.0 | {A18751ED-E493-44C3-A684-602488346594} | {"x": -13608807.749499999, "y": 4591204.668700... |
6 | 7 | US | {8EB57C5B-100B-4C50-B6B1-4D6B9B1C7545} | S | SW | 37.950000 | -121.300000 | STOCKTON | SCK | -13503050.0 | 4572365.0 | {A2688CB5-CDFB-4A8A-B76F-F0AB0D1FCAAC} | {"x": -13503054.233199999, "y": 4572364.8957, ... |
7 | 8 | US | {3B7B126E-0B60-49AF-89AA-4AC05402CFEA} | S | SW | 38.583333 | -121.500000 | SACRAMENTO | SMF | -13525320.0 | 4662162.0 | {A86D6850-70B8-43B6-BB66-73B5E4D46C48} | {"x": -13525318.1314, "y": 4662162.127899997, ... |
8 | 9 | US | {20378B4B-3E9E-47D2-AF42-4F0A31D5CA66} | S | SW | 40.800000 | -124.183333 | EUREKA | ACV | -13824030.0 | 4982886.0 | {A01048CF-CE39-44FE-AF40-B3F792D2DE9E} | {"x": -13824025.3946, "y": 4982886.316600002, ... |
9 | 10 | US | {782C11E0-B02D-45AB-8BAD-97C1B5817812} | M | SW | 43.400000 | -124.283333 | EMPIRE | None | -13835160.0 | 5373055.0 | {7B19D43F-DD50-48C6-BBD3-01930B3605A4} | {"x": -13835157.3437, "y": 5373055.471900001, ... |
10 | 11 | US | {888593DC-D385-4A7C-A1F0-C9D46AB91353} | S | SW | 43.366667 | -124.216667 | COOS BAY | None | -13827740.0 | 5367950.0 | {B63F5915-F764-46A1-BA81-1209BDEA3438} | {"x": -13827736.1185, "y": 5367949.881800003, ... |
11 | 12 | US | {A04935D7-314D-43D3-AA39-99E91FE93BD5} | M | SW | 32.716667 | -117.183333 | SAN DIEGO | SAN | -13044790.0 | 3857756.0 | {A325CED6-0C85-46D3-9524-B0E253ECFBFA} | {"x": -13044788.958999999, "y": 3857756.351199... |
12 | 13 | US | {45CCFAFA-CE13-4EEE-907A-5C53A486C434} | M | SW | 33.766667 | -118.183333 | LONG BEACH | LGH | -13156110.0 | 3997514.0 | {A904E129-30BE-41C5-B0F6-ABB5C8521FE7} | {"x": -13156108.4498, "y": 3997513.9714, "spat... |
13 | 14 | US | {ECA58B5E-ADBB-4392-A6F2-1F5476E69375} | S | SW | 36.616667 | -121.883333 | MONTEREY | MRY | -13567990.0 | 4385809.0 | {63CEB887-33E7-46AF-8710-9DDD4E2F3C19} | {"x": -13567990.5657, "y": 4385808.953900002, ... |
14 | 15 | US | {9B472045-E648-4371-906A-FCC35A7CB0B1} | L | SW | 45.516667 | -122.666667 | PORTLAND | None | -13655190.0 | 5703230.0 | {9A803AB5-5EB9-4BA2-AA17-CB708E3CD92C} | {"x": -13655190.9077, "y": 5703230.203000002, ... |
15 | 16 | US | {B8AC37F8-5AA6-4D27-A401-7B35A8E4B9D3} | S | SW | 21.950000 | -159.350000 | NAWILIWILI BAY | None | -17738760.0 | 2505523.0 | {0C4B2263-59C7-463B-AF9C-284C07B8DFB0} | {"x": -17738760.8579, "y": 2505523.1952, "spat... |
16 | 17 | US | {6D718925-1CF2-4A45-9E3D-B4FBE215BA71} | S | SW | 21.900000 | -159.583333 | PORT ALLEN | None | -17764740.0 | 2499523.0 | {59634BC9-1CDE-4F56-84F1-0C29C6787169} | {"x": -17764735.3687, "y": 2499523.2661000006,... |
17 | 18 | US | {50ECBCE3-137E-45BF-A42E-F0D423434067} | M | SW | 21.300000 | -157.866667 | HONOLULU | HNL | -17573640.0 | 2427687.0 | {A9E9A7A1-4D5E-42C7-9F53-D09C3E04D441} | {"x": -17573636.9837, "y": 2427686.5436000004,... |
18 | 19 | US | {9168C51F-28FF-4885-AFD5-18A1607E3808} | S | SW | 20.033333 | -155.833333 | KAWAIHAE | None | -17347290.0 | 2276980.0 | {7E86F7D7-4E2E-43BC-893A-09D0F1E78092} | {"x": -17347287.2782, "y": 2276980.0967999995,... |
19 | 20 | US | {A2A35C01-C1D4-4FD0-B74E-424E1A9DE20F} | M | SW | 19.733333 | -155.066667 | HILO | ITO | -17261940.0 | 2241467.0 | {1F6FCB1A-7F2D-4DC9-9571-05E685D2A66A} | {"x": -17261942.4095, "y": 2241467.1730999984,... |
20 | 21 | US | {BC904585-28E5-4995-9F6F-BCBDEE4D00C2} | M | SW | 45.633333 | -122.683333 | VANCOUVER | None | -13657050.0 | 5721784.0 | {57CDFEA4-FA11-41C4-8A69-943C5114CDC0} | {"x": -13657046.1584, "y": 5721784.0173999965,... |
21 | 23 | US | None | L | SW | 33.750000 | -118.250000 | LOS ANGELES | LAX | NaN | NaN | {F5FCFF4C-ED2F-4C72-80EF-B414EF4C8C5B} | {"x": -13044788.958999999, "y": 3857756.351199... |
We no longer see 'Redlands', as intended. We also see a new objectid
of 23 corresponding to Los Angeles, which we added. And finally, the short_form
of San Francisco is corrected to 'SFO'. Hooray!
The edits we performed on the features are persisted in the feature layer and will reflect in all clients accessing it.