CodeBreak 30/03/2022

Revision as of 20:04, 11 April 2022 by C.carouge (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Error in Python

The person was trying to reproduce an example Python program. It output the error:

AttributeError: 'function' object has no attribute ‘compute’  

This happened because the person had omitted the parentheses on a previous call to another function. For example, the code below will return the same error:

a=xr.DataArray([1,2])
b=a.mean
b.mean()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'mean'

On the second line, b=a.mean will return a reference to the meanfunction associated with the DataArray a. In other words, b is the mean function, not its result. That is why the error message starts with ‘function’ object

To get the results from the function, you need to call the function which is done with the () and any argument you need to give.

Avoiding repetition in python through code organisation

It is quite common when starting to write a code to just copy and paste a group of lines if we want, for example, to execute the same calculation on a different variable. If you find that you are doing that a lot, it might be time to go back and re-organise your code. A better organised code is not only more readable but is easier to fix should you find a bug. A well-organised code will limit the number of copied lines so you only have to fix your code in one point.

One simple step is to try to create a function for every block of code you are repeating, using only the variables and parameters that might change between calls as arguments.    

def myfunction( row, array ):

       param = …  # this doesn’t change no need to use it as an argument for the function
       … Your calculation …

       return newarray  

In the case we looked at, one function was applied to each row of a pandas dataframe. To do so we can use the pandas dataframe itterrows() method and append each result to a list.   

results = []
for index, row in df.iterrows():
    results.append( myfunction(row, array) )   

Basically iterrows() loops across each row of the dataframe and returns the index and the row itself. 

The results list can then be concatenated into one dataArray

final = xarray.concat(results, dim='mydim')  

Another example we looked at was a function to create a subplot, which was then called on different variables, each representing a different region. In such a case, to handle different titles and parameters it can be handy to use a dictionary.  

regions = {'east': [mslp_east, 1, 'Eastern Australian NRM region'],
           ‘north’: [mslp_north, 2, 'Northern Australian NRM region'], … }   

Then you can use the key/values pair to call the same function on each region:  

for k in regions.keys():
    fig = subplot(regions[k][0], regions[k][1], regions[k][2])  

The dictionary method keys() here works in a similar way to iterrows() but returns only the key. Use items() if you want the key,value pairs and values() if you want only the values.

Count the number of elements that follow a given condition

A question was to count how many events with positive values there are for each grid point given an array like anom(event, lat, lon). xarray has a function count(). This will count the number of valid values along the given dimensions. So we need to filter out the negative values using where() and then count() the number of values left along the "event" dimension.

positive_count = anom.where(anom > 0).count(dim=’event’)