POST
|
OK, folks. Thanks to your help, I've learned enough to solve the problem. I'll put the code below, but first a couple of comments, which hopefully will help anyone who is trying to solve similar problems who comes across this thread: First, @JohannesLindner 's point is critical for any of this: the problem I'm trying to solve involves working with featureclasses, not featurelayers! So my opening sentence from my query is completely mis-stated. It reads "I've got a gdb containing many many layers...". In fact the situation is that I've got a gdb containing many many feature classes! Second, my initial query describes what I needed to do as "merge" these classes. There is a tool called merge in arcpy, and it probably could be used to do what I needed done. But it is documented in a way that (at least for me), made it hard to distinguish some of the critical steps involved. The tool that I was able to make work is called "append". It has the advantage that the example arcpy code in its documentation is solving EXACTLY THE SAME PROBLEM I was trying to solve! Finally, a key challenge in the problem I was trying to solve is to write the code in a way that allows for carefully keeping track and displaying how the fields from multiple classes that are hold the same data have different names. What you'll see in the code below is that I've tried to solve this problem by creating a python class that will hold the critical data about how fields are named for each arcgis class. I then create an instance of this class corresponding to each featureclass, and loop through that, pulling the relevant data from each one as needed. The key python trick in making this all work is liberal use of `getattr()` inside the loops! The structure of the code is exactly the same as in the code example for "append", except that what I've written iterate through lists of the relevant featureclasses and fields. What you'll see below is the code for just two featureclasses. In reality, I'm have to append data from thirty!...but the real code is too long to post here! #set the workspace to the gdb holding the features for each municipality
arcpy.env.workspace = ###OMITTED###
#create the receiving featureclass
cw_fc = arcpy.CreateFeatureclass_management(
out_path=###OMITTED###,
out_name="countywide.shp",
geometry_type="POLYGON",
spatial_reference=###OMITTED###
)
arcpy.management.AddField(
in_table=cw_fc,
field_name="MUNICIPALI",
field_type="TEXT",
field_alias="MUNICIPALI"
)
arcpy.management.AddField(
in_table=cw_fc,
field_name="ZONE_ABBR",
field_type="TEXT",
field_alias="ZONE_ABBR"
)
arcpy.management.AddField(
in_table=cw_fc,
field_name="ZONING",
field_type="TEXT",
field_alias="ZONING"
)
#define the class of objects that will hold the data we need for each successive input class
class InLayer():
def __init__(self, layer, muniNM, zone_abbrNM, zoningNM) :
self.layer = layer
self.MUNICIPALI = muniNM
self.ZONE_ABBR = zone_abbrNM
self.ZONING = zoningNM
#enter the data (only 2 classes here...the real one will contain 30)
inlayers = [
InLayer(
layer = 'Brighton_Zoning',
muniNM = "MUNICIPALITY",
zone_abbrNM = "ZONE_ABBR",
zoningNM = "ZONING"
),
InLayer(
layer = 'Brockport_Zoning',
muniNM = "MUNICIPALITY",
zone_abbrNM = "ZONE_ABBR",
zoningNM = "ZONING"
)
]
#create fieldmappings object for appending this layer
fieldmappings = arcpy.FieldMappings()
#add the target shp to the field mappings to set the schema
fieldmappings.addTable(cw_fc)
#Loop through the fields that need to be mapped
for fld in ["MUNICIPALI", "ZONE_ABBR", "ZONING"] :
#create a fieldmap
fldMap = arcpy.FieldMap()
#loop through the layers populate the input side of the fieldmap
for lyr in inlayers :
#add the input field for the current layer
fldMap.addInputField(lyr.layer, getattr(lyr,fld))
#set the output field name
oname = fldMap.outputField
oname.name, oname.aliasName, oname.type = fld, fld, "TEXT"
fldMap.outputField = oname
#add the outputfield to the fieldmappings object
fieldmappings.addFieldMap(fldMap)
#It should now be the case that fieldmappings is populated with all of the relevant inputs, matched to the appropriate outputs!
#so...append!
arcpy.Append_management(
inputs=[getattr(lyr, "layer") for lyr in inlayers],
target=###OMITTED###,
schema_type="NO_TEST",
field_mapping=fieldmappings,
subtype=""
)
... View more
09-15-2021
11:08 AM
|
0
|
0
|
934
|
POST
|
Ah...this is great! You're reply lead to some searching that lead to this stackexchange thread...and now things are starting to feel more clear! Thank you!
... View more
09-14-2021
02:03 PM
|
0
|
0
|
954
|
POST
|
Thank you all! I will try re-specifying the path (thank you, @DanPatterson !), look into whether one of the fields I'm trying to delete is "required" (thank you, @DanLee !) or bound by a temporary join (thank you, @DanPatterson ! ) @JohannesLindner your answer is pitched at exactly the level I need. At this point, part of what I find so challenging about ArcGIS is that I'm mystified by the object model. Any pointers to where I can find a primer on data types in ArcGIS, and what exactly determines which ones (when in-memory) are mutable in what conditions? Oh yea...and also, which operations are the ones that write to disk and which only modify objects in-memory? Programming without this basic knowledge of the data and i/o models is scary! I need a primer! Thanks! -Stu
... View more
09-14-2021
01:52 PM
|
0
|
0
|
954
|
POST
|
Apologies in advance for asking for help on something very basic. I've got a gdb containing many many layers. I need to grab just a couple of fields out of each layer and merge them all together into a single layer. Fields across layers have different names but the same content. I'm wanting to do it all in a Python notebook because I need to document every little step. I'm coming from R and this would be a breeze there. But struggling to learn basic data management in arcpy. Anyway, I'm failing in the first step just trying to delete fields in a newly created layer. My guess: I'm supposed to be working with a 'Table' and instead I'm working with a 'Feature Layer'...y'all can tell me whether that's right. Here's what I've done so far. First, I set my workspace to the gdb containing all the layers. Then I'm creating the feature layer in-memory that will be the ultimate output layer: arcpy.management.MakeFeatureLayer('Brighton_Zoning', 'out_layer') ('Brighton_Zoning' is one of the layers in the gdb). Now, there's only four fields I'm ultimately going to want in out_layer: ZONE_ABBR, ZONING, MUNICIPALITY and SHAPE. But what I just did above is put ALL the fields from Brighton_Zoning (there are a lot) into 'out_layer'. So next step is to delete all those excess fields. So let's just try this one at a time...we'll start with a field called 'OBJECTID_12'. Here we go arcpy.DeleteField_management("out_layer", "OBJECTID_12") And...that throws an error: I've tried this with several of the other field names. Also tried it with a list of the field names. Also tried it with single quotes instead of double quotes. Clearly, there's something very very very basic about ArcGIS I do not understand. I need to read a book about it! Oh wait, I did! I read this: https://www.amazon.com/Python-Scripting-ArcGIS-Paul-Zandbergen/dp/1589484991/ref=sr_1_4?dchild=1&keywords=arcpy+and+arcgis&qid=1631567175&sr=8-4 That's the recommend book from esri on arcpy. But here's the thing...it teaches you how to modify data row-by-row (i.e. arcpy.da with cursors). It doesn't teach how to manage the structure of entire tables/features/datasets. So if anyone knows of a book that teaches how to data munge in arcpy (i.e. manipulate fields, table joins, row binds, etc. etc.) please point me that way! And if you can explain the error above, please do! Thanks!
... View more
09-13-2021
02:11 PM
|
0
|
7
|
1029
|
POST
|
I'm having some trouble getting a Python script authenticated via the OAuth 2.0 method described here: Working with different authentication schemes | ArcGIS for Developers Following those instructions, I've created a Python App in my organization. My script then does: from arcgis.gis import GIS gis = GIS("https://pythonapi.playground.esri.com/portal", client_id='************') (Obscuring the client_id so as not to expose my organization to the whole world!) Output (in Jupyter Notebook) is this: (note I've replaced the client_id in the url below with '**********' Please sign in to your GIS and paste the code that is obtained below. If a web browser does not automatically open, please navigate to the URL below yourself instead. Opening web browser to navigate to: https://pythonapi.playground.esri.com/portal/sharing/rest//oauth2/authorize?response_type=code&client_id=************&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&state=TiM8EYsGY0fZgXAndvPSphHA2LbsDD Enter code obtained on signing in using SAML: I click on the link and get this in my browser: What's going wrong? (By the way, I recognize that it may be impossible to troubleshoot without sharing the client_id. If that's the case...oh well!) One possibility: I'm running jupyter notebook on a (headless) server in my office at work. But I'm accessing the server from my chromebook at home. So when the script executes, the request being sent to pythonapi.playground.esri.com is coming from my office server. But then I'm clicking on the link from my chromebook at home, so THAT request arriving at pythonapi.playground.esri.com from a different IP and a different machine. Perhaps this causing some kind of mis-match in the request headers (the one from the script vs the one from the browser) that causes the "Invalid client_id" error? Help!
... View more
10-02-2020
02:31 PM
|
2
|
2
|
1398
|
Title | Kudos | Posted |
---|---|---|
2 | 10-02-2020 02:31 PM |
Online Status |
Offline
|
Date Last Visited |
08-17-2022
01:27 PM
|