Reputation: 531
I am working with some NetCDF files. In order to produce readable plots, I wish to smooth daily data over long time periods. I did this small function for that:
def mov_avg(x,window,min_count=None,axis=-1):
import bottleneck as bn
yy=np.ma.filled(np.ma.fix_invalid(x),np.nan)
yyF=np.ma.masked_all(yy.shape)
xtmp=bn.move_mean(yy,window,min_count=min_count,axis=axis)
wd1=(window-1)/2
ndim = len(yy.shape)
#print xtmp.shape,ndim,axis,window,wd1
if ndim ==1 :
#print wd1,-wd1,wd-1
yyF[wd1:-wd1]=np.ma.fix_invalid(xtmp[window-1:])
elif ndim == 2:
if axis==-1 or axis==1:
yyF[:,wd1:-wd1]=np.ma.fix_invalid(xtmp[:,window-1:])
elif axis==0:
yyF[wd1:-wd1,:]=np.ma.fix_invalid(xtmp[window-1:,:])
return yyF
unfortunately when I use this function on one of my variable times series as in the following code:
for station in stations:
for variable in variables:
os.chdir(inbasedir + variable + "_albedomodis2/")
albmerge = "%s/%s_%s_merged.nc"%(inbasedir + variable + "_albedomodis2/",station,variable)
albnc = Dataset(albmerge, 'r+')
obs = albnc.variables[variable + '_obs'][:,0,0]
obs_smooth = mov_avg(obs,7)
I got the following error message:
TypeError Traceback (most recent call last)
<ipython-input-10-025f4573f745> in <module>()
12 ctessel_alb = albnc.variables[variable + '_ctessel'][:,0,0]
13
---> 14 obs_smooth = mov_avg(obs,7)
15
16
<ipython-input-3-c01b37a40c9a> in mov_avg(x, window, min_count, axis)
10 if ndim ==1 :
11 #print wd1,-wd1,wd-1
---> 12 yyF[wd1:-wd1]=np.ma.fix_invalid(xtmp[window-1:])
13
14 elif ndim == 2:
/home/david/anaconda3/lib/python3.6/site-packages/numpy/ma/core.py in __setitem__(self, indx, value)
3351 elif not self._hardmask:
3352 # Set the data, then the mask
-> 3353 _data[indx] = dval
3354 _mask[indx] = mval
3355 elif hasattr(indx, 'dtype') and (indx.dtype == MaskType):
TypeError: slice indices must be integers or None or have an __index__ method
Yes obviously my data is not integer... Does anyone knows how to overcome this error?
Upvotes: 0
Views: 475
Reputation: 107
I think I figured it out. I haven't tested it for Python 2 yet but I think I know why it doesn't work in Python 3.
In your first code block defining the function mov_avg
your first two arguments are x
and window
. In the function you have the line:
wd1=(window-1)/2
When you call the function you call it as:
obs_smooth = mov_avg(obs,7)
where window=7
. Within the function body wd1
is calculated, but it doesn't evaluate to 3, it evaluates to 3.0 - a float value, not an integer. So when it tries to do the line starting with yyF[:,wd1:-wd1]
, it fails because wd1 isn't an integer.
You could try to use the int()
function to convert it to a float.
I tested accessing a sample list using float and integer values on a default installation of Python 3.6.5 installed using Conda.
Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [1,2,3,4,5]
>>> a[0], a[4]
(1, 5)
>>> a[0.0,4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not tuple
And in the specific case of your code:
>>> window = 7
>>> wd1 = (window-1)/2
>>> wd1
3.0
>>> a[wd1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers or slices, not float
EDIT: In Python 2, the result of the last operation would be an integer, not a float. Perhaps this is why it is working on Python 2 but not Python 3?
Disclaimer: I'm new to programming so if this isn't the reason, sorry! I'm trying to learn more by attempting a few questions on SO I can understand.
Upvotes: 2