Rasterio Yearly Temperature Data – Creating Yearly Average Temperature Data from Monthly Data Bands in Raster File Using Rasterio

geotiff-tiffpythonrasterrasterio

I want to create yearly average temperature for grid cells in a raster file based on monthly data. I have a multiband raster with 1380 bands, each corresponding to 1 month from 1900 till 2014. Now I would like to use python to read the .tif file, extract years by extracting 12 bands at a time (bands 1-12 for year 1900, bands 13-24 for year 1901 and so on), calculate the mean over the 12 extracted bands and save it in a new raster.

My approach was as follows:

india_temp = rio.open(r'monthly_mean_temp.tif')
year = {}
r = list(range(1,13))
integers = [12] * 12
for p in range(1900,2015):
    year[p] = india_temp.read(r) #read in 12 months/bands steps
    months1 = year[p].indexes
    month1 = dict()
    for i in months1:
        month1[i] = year[p].read(i)
        
    mean_band = np.mean(list(month1.values()))
    
    with rio.open(r'empty1.tif') as src:
        ras_data = src.read()
        ras_meta = dataset.profile

    # changes to raster properties:
    ras_meta['dtype'] = "float32"
    ras_meta['nodata'] = -99

    with rio.open(r'monthly_mean_temp_' + str(p) + '.tif', 'w', **ras_meta) as dst:
        dst.write(mean_band, 1)    
        
    for index, integer in enumerate(integers):
        r[index] += integer 

There are apparently several mistakes in the code and I tried some other coding as well but since I am quite new to python and QGis, I don't know what I could do to solve the issue.

Best Answer

No need to loop through each month, you can just pass an iterable of month indexes to the read method, e.g. src_dataset.read(indexes)

For example:

import rasterio as rio

years = (1900, 2015)

src_filename = 'monthly_mean_temp.tif'
dst_filename = 'yearly_mean_temp_{}.tif'

with rio.open(src_filename) as src:
    profile = src.profile
    profile.update(
        dtype="float32",
        nodata=-99,
        count=1
    )

    for year in range(*years):
        start_month = (year-years[0]) * 12 + 1
        months = range(start_month, start_month+12)
        monthly_mean = src.read(months).mean(axis=0)
        with rio.open(dst_filename.format(year), "w", **profile) as dst:
            dst.write(monthly_mean, 1)

If you wanted to create yearly data beginning in July of each year, you could use:

start_month = ((year-years[0]) * 12 + 7)

But I haven't tested this so don't know if it will fail in the last year when you only have July-Dec instead of July-June.