Using Esri Desktop Advanced 10.2.2 is it possible to create an attribute based on a classification method, i.e. Jenks? To elaborate - if you use the symbology tab in a layers properties, you can set a classification method that displays the class breaks, but I want to also do some statistical analysis based on those class breaks. Previously, I have done this by performing the classification using the layer properties and then using the class breaks to do a SQL and manually editing a attribute field with the class number. This works, but is labor intensive. Is there a progamatic way to do this?
import arcpy, pysal from pysal.esda.mapclassify import Natural_Breaks as nb myArray = arcpy.RasterToNumPyArray(<PATH TO RASTER HERE>) breaks = nb(myArray.ravel(),k=<NUMBER OF CLASSES HERE>,initial=20)
I believe there is a more programmatic way, however it only automates the steps you have already described. I don't readily know of a more efficient way to automate for this effect.
First, my gut reaction says to use arcpy.mapping to grab a reference to your target layer object, access the layer.symbology object and then extract the layer.symbology.classBreakValues list. Once we have the list of class break values for your Jenks classification, we'd have to go back and use an arcpy.da.UpdateCursor() to assign category values to your data conditionally, based on the classification bounds found in the layer.symbology.classBreakValues list. These category values would be placed in a new field, maybe called "BreakClass." Then, when all of your records have a value for "BreakClass" we could move on with further statistical analysis, grouping-by our "BreakClass" labels. The following assumes ArcGIS 10.2.2 and that the data we are working with is local to your machine, on-disk.
This also assumes we are working with only 3 jenks classes. I'm having some trouble figuring out a generalized way to push the classifier bounds over the data using an arbitrary number of class breaks - maybe need to def a function for this - comments welcome! Thinking overall it may look something like this - Good Luck:
import arcpy target_jenks_layer = arcpy.mapping.Layer("C:\\path\\to\\the\\layer\\file") # for example, where the target layer support symbology and uses graduated colors... if target_jenks_layer.supports("SYMBOLOGY"): if target_jenks_layer.symbologyType == "GRADUATED_COLORS": jenks_breaks_list = target_jenks_layer.symbology.classBreakValues jenks_labels_list = target_jenks_layer.symbology.classBreakLabels for break_value in jenks_breaks_list: print(break_value) # elif target_jenks_layer.symbologyType == "GRADUATED_SYMBOLS........etc # add the field to the data which will hold the "BreakClass" labels if target_jenks_layer.supports("DATASOURCE"): arcpy.AddField_management(target_jenks_layer.dataSource, "BreakClass", "TEXT") # start classifying the data using the breaks values as conditional bounds cursor = arcpy.da.UpdateCursor(target_jenks_layer.dataSource, [target_jenks_layer.symbology.valueField, "BreakClass"]) for row in cursor: test_value = row if test_value > jenks_breaks_list and test_value <= jenks_breaks_list: row = jenks_labels_list cursor.updateRow(row) elif test_value > jenks_breaks_list and test_value <= jenks_breaks_list: row = jenks_labels_list cursor.updateRow(row) elif test_value > jenks_breaks_list and test_value <= jenks_breaks_list: row = jenks_labels_list cursor.updateRow(row) del row del cursor print('Finished applying break labels to dataset')