Using the [post](https://geonet.esri.com/blogs/richard_fairhurst/2014/11/08/turbo-charging-data-manipulation-with-python-cursors-and-dictionaries) of Richard Fairhurt and this [post](https://geonet.esri.com/blogs/dan_patterson/2015/09/28/circular-mean-for-directional-data) for the bearing average I came up with the following solution: import math fc= "e:/NCCA/Temp/Temp.gdb/table_three" bearings = ["IN_FID", "bearing", "bearing_avg"] def calc(): #creates a dictionary with the IN_FID as the key, and the bearing as the values valueDict = {} with arcpy.da.SearchCursor(fc, bearings) as searchRows: for searchRow in searchRows: keyValue = searchRow[0] if not keyValue in valueDict: valueDict[keyValue] = [searchRow[1]] else: valueDict[keyValue].append(searchRow[1]) #calculates the bearing average of the values for each dictionary key and puts the average bearing into a new dictionary averageBearingDict = {} for key in valueDict: cosSum = 0.0 sinSum = 0.0 for bearingVal in valueDict[key]: theCos = math.cos(math.radians(float(bearingVal))) theSin = math.sin(math.radians(float(bearingVal))) cosSum += theCos sinSum += theSin N = len(valueDict[key]) C = cosSum/N S = sinSum/N theMean = math.atan2(S,C) if theMean < 0.0: theMean += math.radians(360.0) theMean_deg = math.degrees(theMean) averageBearingDict[key] = theMean_deg #this puts the calculated bearing average back into the table - in row "bearing_avg" with arcpy.da.UpdateCursor(fc, bearings) as rows: for row in rows: row[2] = averageBearingDict[row[0]] rows.updateRow(row) This runs within the code block of the calculate field tool, within modelbuilder, with the expression set to calc().