I am trying to compare the occurrences of codes from a column within feature classes against a list from a spreadsheet column and then add these to a dictionary where the feature class name is the key and the values are a count of unique occurrences between the two columns. I then need to sum all the value counts for each key. I can make this work to a degree, the problem is that codes are being appended and counted multiple times. How can I make this code work so that code occurrences are only counted once? Here is what I have so far:

FacID = []
with arcpy.da.SearchCursor(IDL,['FACILITY_ID']) as cursor:
    for row in cursor:
FC_FacID = {}
for element in CCMList: ## CCMList is just a list of feature classes (Building, Bridge, etc)
    with arcpy.da.SearchCursor(element,['facilityIDFK']) as cursor_ig:
        for row in cursor_ig:
            key = (element)
            code = (row[0])
            if key not in FC_FacID.keys():
                FC_FacID[key] = []
            if code not in FC_FacID.values():
FC_FacID_Count = {}
for name,code in FC_FacID.items():
    FC_FacID_Count[name] = sum(code)

Sample data:
FacID = [u'NFA001, u'NFA002, u'NFA003]
Feature Class 'facilityIDFK' column: Building(NFA001, NFA001, NFA002, NFA005) #In this example NFA001 appears twice but needs to only be counted once
FC_FacID should look like {u'Building: [1, 1, 0]}
FC_FacID_Count should look like {u'Building: 2}

  • I'm not completely clear on what you want to do. Can you give an example of your input data and what you expect the output to look like?
    – JCVanHamme
    Aug 4 '16 at 14:46
  • @JCVanHamme FacID: [u’NFA001’, u’NFA002’, u’NFA003], CCMList: [u’Building’, u’Bridge’], Feature Class ‘facilityIDFK’ column can have values like this: Building: “NFA001, NFA001, NFA002, NFA005”, Output: Code only appended - FC_FacID: {u’Building’: [u’NFA001’, u’NFA002’, u’NFA005’]} , Count of code comparison appended - FC_FacID: {u’Building’: [1, 1, 0]}.
    – DanMilRiv
    Aug 4 '16 at 15:17
  • @JCVanHamme The code appears to be ignoring the line “if code not in FC_FacID.values():” and is just adding all row entries for the ‘facilityIDFK’ column from the feature classes whether it is already in the dictionary’s values or not. So I am getting FC_FacID: {‘Building’: [u’NFA001’, u’NFA001’, u’NFA002’, u’NFA005’’} or FC_FacID:{u’Building’: [1, 1, 1, 0]} instead of the desired results.
    – DanMilRiv
    Aug 4 '16 at 15:20
  • Please use the edit button beneath your question to revise it.
    – PolyGeo
    Aug 4 '16 at 15:26

There are a couple of issues with your code that I see. First, in FC_FacID, the values that you are storing are lists. Then in your second if statement, you're checking to see if code is present in the values of FC_FacID. This will never evaluate to true since you're comparing strings or ints or whatever the type of facilityIDFK is to lists. Second, your second if is looking for code in the values, but the values that you're putting in there are counts, so the codes will probably never match, or if they do, they won't be doing what you expect.

I'm assuming that what you want is something like a count of code for each (element, code) pair, something like:

element    code    count
el_1       0001    10
el_1       0002    2
el_2       0003    4
el_3       0003    5
el_3       0004    1

There are a couple of ways to get this. You could consider a nested dictionary and do something like

for element in CCMList: 
    with arcpy.da.SearchCursor(element,['facilityIDFK']) as cursor_ig:
        for row in cursor_ig:
            key = element # your parens here are unnecessary
            code = row[0]
            key_dict = FC_FacID.get(key, {})
            if code not in key_dict:
                key_dict[code] = FacID.count(code)
            FC_FacID[key] = key_dict

Alternatively, it might be a little tidier to just use an (element, code) tuple to index your dictionary, like this:

for element in CCMList: 
    with arcpy.da.SearchCursor(element,['facilityIDFK']) as cursor_ig:
        for row in cursor_ig:
            code = row[0]
            key = (element, code)
            if key not in FC_FacID:
                FC_FacID[key] = FacID.count(code)

If you then want to sum up the entries for each element, you can do that too. Using my mock up data above, this would give you a result like {'el_1': 12, 'el_2': 2, 'el_3': 6}. To do that with the nested dictionary approach, you could do:

result = dict([(key, sum(FC_FacID[key].values()) for key in FC_FacID])

or equivalently if you're not comfortable with list comprehensions:

result = {}
for key in FC_FacID:
    result[key] = sum(FC_FacID[key].values())

with the tuple-indexed approach I'd do:

result = dict([(key[0], sum([FC_FacID[key2] for key2 in FC_FacID if key2[0] == key[0]]) for key in FC_FacID])

Without the list comprehension, this one's a little more verbose

result = {}
for key, code in FC_FacID:
    count = result.get(key, 0)
    count += FC_FacID[(key, code)]
    result[key] = count
  • Is there a way to then sum all the count values for each key so that you can create a product that looks like: {u'Building': 10, u'Bridge': 5}
    – DanMilRiv
    Aug 4 '16 at 16:16
  • I added some additional discussion as to how to sum the results.
    – JCVanHamme
    Aug 4 '16 at 17:17
  • Thank you very much, that all worked perfectly. I went with the nested dictionary solution.
    – DanMilRiv
    Aug 4 '16 at 18:34

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.