Select to view content in your preferred language

ModelBuilder how to compare several fields between 2 FCs

2919
7
Jump to solution
02-25-2016 03:39 PM
JoseSanchez
Frequent Contributor

Hello everyone,

I need to check if features from one FC match features from another feature class. For this purpose I need to compare 3 fields from the first FC to 3 fields from the second FC.

How can I compare 2 feature classes using more than one field? With one field I can use join a join. Is is possible to join several fields between 2 FCS?

Do I need to do this compare in python or vb.net?

Thanks

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

Probably the easiest way to do this is using Python. You mention ModelBuilder. You can create a tool with Python and add it to ModelBuilder. What do you want to do with the matching features?

View solution in original post

0 Kudos
7 Replies
XanderBakker
Esri Esteemed Contributor

Probably the easiest way to do this is using Python. You mention ModelBuilder. You can create a tool with Python and add it to ModelBuilder. What do you want to do with the matching features?

0 Kudos
JoseSanchez
Frequent Contributor

Hi,

I am comparing two different days of the same feature class and I am looking for unmatched features to find records inserted and deleted.

Thanks

0 Kudos
XanderBakker
Esri Esteemed Contributor

And what should be the output of the tool? A list of differences of a selecting of features?

What if a feature geometry or an attribute that is not being considered in the validation, has been changed?

0 Kudos
JoseSanchez
Frequent Contributor

Good questions!

Can you help me with an answer?

0 Kudos
XanderBakker
Esri Esteemed Contributor

To help you a bit,  have a look at the tool and code below:

Parameters:

  • 0: FeatureLayer (1)
  • 1: Field (multivalue, derived from featurelayer1)
  • 2: Featurelayer (2)
  • 3: String (direction output) additions
  • 4: String (direction output) deletes

What you choose to do with the resulting lists defines how they should be defined and formatted as output.

Result:

Code:

def main():
    import arcpy

    fc1 = arcpy.GetParameterAsText(0)
    selected_flds = arcpy.GetParameterAsText(1)

    fc2 = arcpy.GetParameterAsText(2)
    flds = selected_flds.split(';')

    # check if selected fields in fc2
    arcpy.AddMessage('Check if selected fields in fc2')
    for fld in flds:
        if len(arcpy.ListFields(fc2, fld)) == 0:
            arcpy.AddError('ERROR: Field {0} not in {1}'.format(fld, fc2))

    fld_oid1 = arcpy.Describe(fc1).OIDFieldName
    fld_oid2 = arcpy.Describe(fc2).OIDFieldName

    flds1 = [fld_oid1] + flds
    flds2 = [fld_oid2] + flds

    # validation: are the three fields combined unique?
    arcpy.AddMessage('Validation: are the three fields combined unique?')
    if not isUnique(fc1, flds1):
        arcpy.AddError("The combination of the 3 field for FC1 is not unique")
    if not isUnique(fc2, flds2):
        arcpy.AddError("The combination of the 3 field for FC2 is not unique")

    # create dictionary
    arcpy.AddMessage('Create dictionaries')
    dct1 = generateDict(fc1, flds1)
    dct2 = generateDict(fc2, flds2)

    # create sets
    arcpy.AddMessage('Create sets')
    set1 = set(dct1.keys())
    set2 = set(dct2.keys())

    # check additions (in FC2, but not in FC1)
    arcpy.AddMessage('Check additions (in FC2, but not in FC1)')
    adds = [dct2 for a in list(set2 - set1)]
    if len(adds) > 0:
        arcpy.AddMessage('OIDs added: {0}'.format(adds))
    arcpy.SetParameterAsText(3, adds)

    # check deletes (in FC1, but not in FC2)
    arcpy.AddMessage('Check deletes (in FC1, but not in FC2)')
    dels = [dct1 for a in list(set1 - set2)]
    if len(dels) > 0:
        arcpy.AddMessage('OIDs deleted: {0}'.format(dels))
    arcpy.SetParameterAsText(4, list(dels))

def generateDict(fc, flds):
    return {u'{0}#{1}#{2}'.format(r[1], r[2], r[3]): r[0] for r in arcpy.da.SearchCursor(fc, (flds))}

def isUnique(fc, flds):
    lst1 = [u'{0}#{1}#{2}'.format(r[1], r[2], r[3]) for r in arcpy.da.SearchCursor(fc, (flds))]
    return len(lst1) == len(list(set(lst1)))

if __name__ == '__main__':
    main()
0 Kudos
ChrisDonohue__GISP
MVP Alum

If Python is not your thing, another possible approach would be to use the Feature Compare tool

Feature Compare—Help | ArcGIS for Desktop

Chris Donohue, GISP

XanderBakker
Esri Esteemed Contributor

Very true, with the advantage that it will compare all the fields, BUT if the order of the featureclass is changed, it will not be able to detect the changes correctly.

0 Kudos