I am attempting to compare two rasters representing a species distribution model for now and the future.

The rasters have the exact same extent and cell sizes.

here is when is gets tricky, they are multi-band rasters, so to create an attribute table I must first convert them to a binary raster (maybe there is another way around this?). Doing this I lose a lot of the information in the rasters.

I want a quick way to compare how many cells have changed value (using python probably) as I have many sets of these to compare.

  • 1
    Are the bands for the now/future rasters representing the same phenomena? If so, have you tried to compare the individual now bands to their future counterpart? See here for how to read individual bands in arcpy.
    – Barbarossa
    Mar 18, 2016 at 3:15

1 Answer 1


Try this:

  • Use the RasterToNumpyArray function to convert your multi-band raster to n-dimensional array with dimensions (# of bands, rows,columns)
  • Use the not_equal function from the numpy module to undertake a cell by cell comparison for each band.
  • Use the unique function from the numpy module and list comprehensions to find total number of cells that have changed/not changed.


Using simple 3 band rasters (species_n and species_f), the sample code below

import arcpy
import numpy as np

sn = arcpy.RasterToNumPyArray(r'D:\species.gdb\species_n',nodata_to_value = -999.999) #species now
print "\nSpecies Now"
print "Data Type: {0}".format(sn.dtype)
print "Bands, Rows, Columns: {0}\n".format(sn.shape)

sf = arcpy.RasterToNumPyArray(r'D:\species.gdb\species_f',nodata_to_value = -999.999) #species future
print "\nSpecies Future"
print "Data Type: {0}".format(sn.dtype)
print "Bands, Rows, Columns: {0}\n".format(sn.shape)

#Band comparison
#cell by cell comparison - returns true if cell values not equal, else false.
band_comparison = np.not_equal(sn[0],sf[0])

u, indices = np.unique(band_comparison, return_inverse = True)

#Count #number of changed cells
#this step can be replaced with a far more elegant approach
cell_counts = zip(u,[u[indices].tolist().count(x) for x in u])
print "\nChanged Cells:\n{0}".format(cell_counts)

produces the results below:

enter image description here

Note: in this example, band 1 in species_n is exactly the same as band_1 in species_f. The results above show that there are no changed cells, as expected.

species_f(bands 2 and 3) are multiples of species_n(bands 2 and 3)

Band 2 comparison:

band_comparison = np.not_equal(sn[1],sf[1])


enter image description here

10 cells have not changed (in this example, these are just no data cells) 26 cells have changed.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.