4

I'm currently formatting our GIS data for use in a mobile app. The purpose of altering the data is to reduce the output file size that's imported into the app. I need to delete many fields from many feature classes. I will need to run this script about every two months to provide updated data.

The first part of my script copies the feature classes from our SDE geodatabase to a file geodatabase using arcpy.FeatureClassToFeatureClass_conversion(). This function has a field_mapping parameter which I'm not very familiar with.

What would be the quickest way to delete many fields from many feature classes?

Using the field_mapping parameter, or just using arcpy.DeleteField_management()? I would think field_mapping.


The real problem is that I want to remove around 30 fields from each feature class, and only keep around 4-5.

With field_mapping, (I haven't researched this yet) is there a way to simply state only the fields I want to keep without listing all the fields I want to remove too?

  • If the fields are the same every time you need to do this, I would probably script it out using a "ListFeatureClasses" and "deleteField" loop and run it at night when I'm not working. – GeoJohn May 7 '15 at 16:56
  • However, the answer provided below by crmackey could be implemented with a script as well. – GeoJohn May 7 '15 at 16:59
6

Another alternative is to create a feature layer containing only the fields you want, then use arcpy.CopyFeatures_management() or arcpy.FeatureClassToFeatureClass_conversion() to copy the result to a new feature class.

I've written a function called make_skinny() (with two wrappers, make_skinny_feature_layer() and make_skinny_table_view()) that takes a list of the fieldnames you want to keep and returns a layer/view with only those fields. Also accepts an optional definition query to subset the records.

def make_skinny(is_geo, in_obj, out_obj, keep_fields_list=None, where_clause=''):
    ''' Make an ArcGIS Feature Layer or Table View, containing only the fields
        specified in keep_fields_list, using an optional SQL query. Default
        will create a layer/view with NO fields. '''
    field_info_str = ''
    input_fields = arcpy.ListFields(in_obj)
    if not keep_fields_list:
        keep_fields_list = []
    for field in input_fields:
        if field.name in keep_fields_list:
            field_info_str += field.name + ' ' + field.name + ' VISIBLE;'
        else:
            field_info_str += field.name + ' ' + field.name + ' HIDDEN;'
    field_info_str.rstrip(';')  # Remove trailing semicolon
    if is_geo:
        arcpy.MakeFeatureLayer_management(in_obj, out_obj, where_clause, field_info=field_info_str)
    else:
        arcpy.MakeTableView_management(in_obj, out_obj, where_clause, field_info=field_info_str)
    return out_obj

# Wrapper functions for make_skinny()
def make_skinny_feature_layer(fc, lyr, keep_fields_list=None, where_clause=''):
    return make_skinny(True, fc, lyr, keep_fields_list, where_clause)
def make_skinny_table_view(table, view, keep_fields_list=None, where_clause=''):
    return make_skinny(False, table, view, keep_fields_list, where_clause)
  • Do you know where the documentation is on how to format the field_info string? I haven't found anything. – ianbroad May 14 '15 at 2:34
  • I don't think I've ever seen any formal documentation for the string formatting, but I find the pure-Python method for constructing FieldMappings to be overwhelmingly tedious. I mostly reverse-engineered it by specifying a field mapping in a GUI tool and then doing "copy as Python snippet". I believe it's "old_field1_name new_field1_name VISIBLE/HIDDEN;old_field2_name new_field2_name VISIBLE/HIDDEN;...". – nmpeterson May 14 '15 at 14:01
5

I have noticed that the DeleteField tool can be very slow when there are a lot of fields. One thing I have done in the past is created a template table that just has the fields I needed and just copy that blank table and use the arcpy.management.Append() to write features to the template table. Seemed to work pretty well.

  • Yeah, that's a great alternative. I'm going to see if anyone replies about the field mapping, otherwise I'll probably go this route. Thanks for the suggestion. – ianbroad May 7 '15 at 17:18
  • 1
    It would be a tedious work to create empty feature classes with all the fields data types and names, aliases though... – Alex Tereshenkov May 7 '15 at 18:06
  • @AlexTereshenkov yeah, well I wouldn't create them manually. I'd export/import the XML like you had mentioned. – ianbroad May 7 '15 at 18:28
  • 1
    @ian, right, this makes sense. But then you would still need to delete the fields from the schema feature classes... if you have a chance - run SELECT INTO with SQL, this will make your life so much easier :D – Alex Tereshenkov May 7 '15 at 20:29
5

To keep up with folks :) some alternatives

  1. Since you store your data in an enterprise geodatabase (or DBMS without Esri component) - why not take advantage of SQL? This is way faster than running any GP tool or arcpy (for copying data). Run some SELECT INTO statements limiting what columns you want to take and then run arcpy only to copy the tables with spatial column into file geodatabase feature classes. I would go for this if I could - in the SQL call you specify what columns you want to keep, just what you are asking for.

  2. If you will work with many feature classes, the fastest way I am aware of that will let you create a schema of the geodatabase (or some parts of it) is exporting a geodatabase schema to an XML workspace document (GP tool Export XML Workspace Document (Data Management)) and then importing it back to an empty file geodatabase. Delete fields for feature classes that were imported (it is faster to delete fields on empty feature class than on the one with features) with arcpy. Run Append GP tool to load data.

  3. Run FeatureClassToFeatureClass (Conversion) GP tool in ArcMap and set up in the Expression parameter 1 = 0 to not export any feature while deleting the unneeded fields in the Field Map parameter. Then copy the result as Python snippet and embed into your script; the drawback is huge field mappings which are large strings that are hard to work with. Append the source data with NO_TEST option - only data for the fields present in the target dataset will be appended.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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