More

Can I find out the exact areas which each category covers?


I have accessed a land use map and clipped the appropriate area I need to analyse. Is there a way I can find the exact areas which each category covers?


1. Tabulate areas

The more robust method of calculating areas is to use the Tabulate Areas geoprocessing tool within Spatial Analyst. This is intended to calculate a breakdown of areas for classified raster data for a series of zones. For example, if you need the area of each land cover class for each city or town within your study area. To get the total for everything, just pass in the polygon you used to clip your raster as the single zone.

The units of Tabulate Areas are linear unit of the raster's coordinate system


2. Raster attribute table

A less robust but marginally faster way of calculating total area for each land cover class is to look at the raster's attribute table. Right click on the layer in the Table of Contents, and click "Attribute Table". If that option is grayed out, then you'll need to run the Build Raster Attribute Table geoprocessing tool. TheCOUNTfield in this table describes the number of cells with that value. You'll need to multiply this by the area of each cell to get the total area.


I am not sure how much are you familial with R, but I think there is the best and very simple solution of your problem:

library(raster) # read "raster" library setwd("D:/Data/… ") # set you working directory r<-raster("your_raster.tif") # import your category raster file t<-freq(r) # Calculate your raster frequency table - # it means how many pixels belong to 1 # category and save it in a table "t" # hereafter you have to know the area of 1 pixel (following your exemple I suppose it is 1m2). # Multiply that value with the number of pixels in each category - from the second culomn od your table t -> (t[,2]) my.area<-t[,2]*1 # 1 = area of 1 pixel my.area.fin <- cbind(t, my.area) # export table to .txt: write.table(area_fin, file="area_by_category.txt", sep="	")

If you will have any problem with this script, you can send me your image/exemple data and I will adapt the script.

Good luck ! :)


Although you are dealing with an image and not a polygon layer for your land use classifications, a Planning Department would normally have this layer in a polygon format for future planned land uses. My County has such a layer available for download. If you had a Polygon land use layer, you can set up the symbology labels of your layer to show area using arcpy. This script could be adapted to apply to any polygon layer for any single field unique value symbology classification, not just a land use layer.

I use a separator set of characters to split the base label from the area sum added by the script. I just have to be sure the separator is not part of any base label. That way the script can be run over and over with different selections or filters and replace the area values appended to the base labels.

For your map legend you probably would want to select the layer on the Legend dialog's Items page and check the setting to "Only show classes that are visible in the current map extent". That way any unique category that only existed in the master layer and that did not actually exist in the current layer would be excluded from the legend. The script below does respect feature definition queries and feature selections when accumulating the area of each category. However, some additional modifications to the script would be required to make it actually only evaluate the areas of the polygons based on just the current visible extent if the features were not already selected.

Below is a sample script you can add to a script tool. The script works even if you have grouped land use classifications:

# Name: ApplySymWithAreaLabels.py # Purpose: apply the symbology from one layer to another and show area in labels # Import system modules import arcpy from arcpy import env #**** CUSTOMIZE THESE INPUT VARIABLES **** # Set the current workspace env.workspace = r"C:UsersOWNERDocumentsArcGIS" # Assign a string for labeling area units. areaUnitStr = "Acres" # Assign a conversion factor for the area units. Use 1.0 to use the layer's native units in float precision. # Example conversions: # Sq. m to Sq. km = 1.0 / 1000000.0 or 0.000001 # Sq. Ft. to Acre = 1.0 / 43560.0 or 0.0000229568411386593 # Sq. Ft. to Sq. Mi. = 1.0 / 27878400.0 or 0.000000035870064279155 areaUnitFactor = 1.0 / 43560.0 # Set the name of the layer in the map you want to symbolize layerName = "Land Uses" # Separator character(s) variable to split base label from area # make sure the separator is not part of the actual base label separator = ' - ' # Define a label template string. # In particular set the number of decimal places for the second parameter labelTemplate = '{0}' + separator + '{1:,.2f} {2}' #**** SCRIPT BELOW SHOULD NOT NEED REVISION **** # Point to the current active map mxd = arcpy.mapping.MapDocument("current") # Set layer to apply symbology to lyr = arcpy.mapping.ListLayers(mxd, layerName)[0] # Get the field that sets the symbology valueField = lyr.symbology.valueField # Get the list of unique land use categories in the layer classValuesList = lyr.symbology.classValues # Get the list of unique land use labels without area classLabelsList = lyr.symbology.classLabels valueDict = {} # Assign all layer field classification values to a dictionary with the cumulative sum of their areas with arcpy.da.SearchCursor(lyr, [valueField, "[email protected]"]) as searchRows: for searchRow in searchRows: keyValue = searchRow[0] if not keyValue in valueDict: # When keyValue is not in the dictionary insert it and store its area valueDict[keyValue] = searchRow[1] else: # When keyvalue is already in the dictionary cumulatively sum the area valueDict[keyValue] += searchRow[1] # Create a class dictionary to track the cumulative sum of grouped classifications labelsDict = {} # iterate through all class values in the layer for i in range(len(classValuesList)): classValue = classValuesList[i] classLabel = classLabelsList[i].split(separator)[0] if not classLabel in labelsDict: # Initialize the class dictionary with 0 area labelsDict[classLabel] = 0 if classValue in valueDict: # cumulatively sum areas of actual individual layer classes into the grouped classifications labelsDict[classLabel] += valueDict[classValue] classLabelsList[i] = labelTemplate.format(classLabelsList[i].split(separator)[0], (labelsDict[classLabel] * areaUnitFactor), areaUnitStr) # Assign the ordered labels to the classes lyr.symbology.classLabels = classLabelsList # Refresh the Table of Contents to reflect the change arcpy.RefreshTOC() # Refresh the Active View to reflect the change arcpy.RefreshActiveView()

The script created the output below for my land use polygon layer. It converted my native area units from Square Feet to Acres. It would have handled any grouped classifications if I had set them up in the master layer.

You should save a master layer file to disk that has the layer symbols, labels (with out area values) and order set up the way you want it for all possible classes of land use categories as a backup to get the base labels. Unfortunately the Apply Symbology From Layer tool does not respect the category order of the saved layer, so you have to use the manual Desktop Symbology Import option to get the symbols to have the order you saved in your master layer file. Otherwise I would use that tool and not use the Desktop Import button. Support the idea to respect the source layer order when using the Apply Symbology From Layer tool and the Redesign the Symbology Dialog in desktop to make the resorting process easier, since once you get above 10 symbols the current dialog is a pain to override the default sort order.

You may want to change the script to accept parameters so that you could use the script tool to let you choose your output layer, saved master symbol layer, and/or area unit type and conversion factor at runtime. The script could easily be modified to get other statistics, like the sum of the length of each category for polylines or polygon perimeters, or the count of features for any of the geometry types.