Write unique attribute value pairs

3153
3
Jump to solution
07-01-2015 02:10 AM
BenLeslie1
Occasional Contributor III

I've got a python script that looks for a field name in shapefiles and if it exists writes all unique attribute values to a text file, as follows:

testField = "MyField"

with open("myTextFile.txt", "a") as text file:
     fcs = arcpy ListFeatureClasses()
     for fc in fcs:
          fieldList = arcpy.ListFields(fc)
          fieldExists = False
          for field in fieldList:
               if field.name == testField:
                    fieldExists = True
          if(fieldExists):
               values = [row[0] for row in arcpy.da.SearchCursor(fc,(testField))]
               uniqueValues = set(values)
               text_file.write('{}'.format(uniqueValues))
               text_file.write('\n')

Now I want to test for two fields and write all unique pairs of values to a text file and I'm a bit stuck can anyone help?.... (the test for whether the fields exist is easy, I figured that bit out, but how do I find unique pairs of values?)

0 Kudos
1 Solution

Accepted Solutions
BenLeslie1
Occasional Contributor III

Thanks, that's handy to know, but I'm going to give myself the correct answer because I've just figured out how to amend my script:

testField1 = "MyFld1"
testField2 = "MyFld2"

with open ("myTextFile.txt", "a") as text_file:
     fcs = arcpy.ListFeatureClasses()
     for fc in fcs:
          ...
          #section omitted - tests whether each field exists
          ...
          valueList = []
          #test both fields exist and append values to valueList
          if(fieldExists1 and fieldExists2):
               with arcpy.da.SearchCursor(fc,[testField1, testField2]) as cursor:
                    for row in cursor:
                         value = row[0] + "," + row[1]
                         valueList.append(value)
          else:
               print fc + " no valid fields"
          uniqueValues = set(valueList)
          text_file.write('{}'.format('\n'.join(uniqueValues)))
          text_file.write('\n')

View solution in original post

3 Replies
JakeSkinner
Esri Esteemed Contributor

Hi Ben,

You can accomplish this using the Summary Statistics tool.  For example, specify a field and a statistic type for the 'Statistics Field' parameter.  In 'Case Field' parameter, specify the fields you want to find the unique pairings for.

The output table will have a FREQUENCY field.  Values of 1 indicate the unique values for the two fields.

BenLeslie1
Occasional Contributor III

Thanks, that's handy to know, but I'm going to give myself the correct answer because I've just figured out how to amend my script:

testField1 = "MyFld1"
testField2 = "MyFld2"

with open ("myTextFile.txt", "a") as text_file:
     fcs = arcpy.ListFeatureClasses()
     for fc in fcs:
          ...
          #section omitted - tests whether each field exists
          ...
          valueList = []
          #test both fields exist and append values to valueList
          if(fieldExists1 and fieldExists2):
               with arcpy.da.SearchCursor(fc,[testField1, testField2]) as cursor:
                    for row in cursor:
                         value = row[0] + "," + row[1]
                         valueList.append(value)
          else:
               print fc + " no valid fields"
          uniqueValues = set(valueList)
          text_file.write('{}'.format('\n'.join(uniqueValues)))
          text_file.write('\n')
RichardFairhurst
MVP Honored Contributor

Your code will only work with fields that are string, since numeric and date fields cannot be concatenated directly with the comma or each other.  You would have to make line 15 read value = str(row[0]) + "," + str(row[1]).  Additionally if you wish to sort the unique values with the sorted() function, your values will only be correctly sorted for string values and will be incorrectly sorted for numeric or date values.  I would not accept an unsorted list of unique values for my own applications or uses.

You should reverse your field test logic to set the fieldsExist to False if any field does not exist when dealing with a list of fields.  You should be able to make your valueList a list of lists so that you do not need to do concatenation and can handle however many values come at you without any separate code.  The list of lists can also be sorted correctly for each field type (although I have converted the interior list to a tuple, since lists don't work for some functions).  The last couple of lines may have to be revised to run through the list of lists and add a comma separator after sorting (I did not test the code, but above the last two lines it should all work):

fields = [testField1, testField2] # list can contain any number of fields

# Make sure all fields are upper case
for i in range(fields):
    fields = fields.upper()

with open ("myTextFile.txt", "a") as text_file: 
    fcs = arcpy.ListFeatureClasses() 
    for fc in fcs: 
          fieldList = arcpy.ListFields(fc) 
          fieldsExists = True
          for field in fieldList: 
              if not field.name.upper() in fields: 
                  fieldsExists = False
          valueList = []  
          # test all fields exist and append values to valueList
          if (fieldsExists):  
              with arcpy.da.SearchCursor(fc, fields) as cursor: 
                    for row in cursor:
                        fieldValues = []
                        for i in range(fields):
                            fieldValues.append(row)
                        valueList.append(tuple(fieldValues))
          else: 
              print fc + " no valid fields" 
          uniqueValues = sorted(set(valueList))
          text_file.write('{}'.format('\n'.join(uniqueValues))) 
          text_file.write('\n')