means

Contents

means#

Calculate daily, monthly, yearly, etc. means

This module was written by Matthias Cuntz while at Department of Computational Hydrosystems, Helmholtz Centre for Environmental Research - UFZ, Leipzig, Germany, and continued while at Institut National de Recherche pour l’Agriculture, l’Alimentation et l’Environnement (INRAE), Nancy, France.

copyright:

Copyright 2013-2022 Matthias Cuntz, see AUTHORS.rst for details.

license:

MIT License, see LICENSE for details.

The following functions are provided

means(date, dat[, year, month, day, hour, ...])

Calculate daily, monthly, yearly, etc.

History
  • Written Jul 2013 by Matthias Cuntz (mc (at) macu (dot) de)

  • Added meanday, Jul 2013, Matthias Cuntz

  • Added max and min, Apr 2014, Matthias Cuntz

  • Added onlydat and meanmonth, Jun 2015, Matthias Cuntz

  • Added seasonal, Oct 2018, Matthias Cuntz

  • Bug in minute averaging: compared minutes to hours, Jun 2019, Matthias Cuntz

  • Added half_hour, inspired by Robin Leucht for UFZ level1 data; did not take retrospective keyword but added Note for this case, Jun 2019, Matthias Cuntz

  • Use pyjams datetime, Jul 2022, Matthias Cuntz

  • More possible date formats, Jul 2022, Matthias Cuntz

  • Rename seasonal to seasonalday, Jul 2022, Matthias Cuntz

  • Add seasonalmonth, Jul 2022, Matthias Cuntz

  • Add seasonalmeanday, Jul 2022, Matthias Cuntz

  • Use second precision for output dates, Aug 2024, Matthias Cuntz

means(date, dat, year=False, month=False, day=False, hour=False, half_hour=False, minute=False, meanday=False, meanmonth=False, seasonalday=False, seasonalmonth=False, seasonalmeanday=False, sum=False, max=False, min=False, onlydat=False, **kwargs)[source]#

Calculate daily, monthly, yearly, etc. means of data

dat will be averaged over columns, i.e. assuming that the first dimension is the time dimension.

If no keyword argument is given, the mean will be over the whole first column.

date can be either string or datetime object of Python, numpy, cftime, or pyjams, which will be interpreted by pyjams.date2num; or date can be a numeric value, which will be interpreted by pyjams.num2date; any extra keyword argument will be passed to the appropriate datetime routine. Returned dates will be in same format as incoming dates.

Parameters:
  • date (1D array with dates) – Can either be strings or datetime objects of Python, cftime or pyjams, which will be interpreted by pyjams.date2num, or it can be a numeric value, which will be interpreted by pyjams.num2date. date should be centred on the input time period, i.e. half-hourly data should have dates at 15 min and 45 min of each hour, for example.

  • dat (ND (masked-)array)

  • year (bool, optional) – If True, return annual means

  • month (bool, optional) – If True, return monthly means

  • day (bool, optional) – If True, return daily means

  • hour (bool, optional) – If True, return hourly means

  • half_hour (bool, optional) – If True, return half-hourly means

  • minute (bool, optional) – If True, return minute means. Note that this can take very long.

  • meanday (bool, optional) – If True, return one mean daily cycle

  • meanmonth (bool, optional) – If True, return mean monthly cycle

  • seasonalday (bool, optional) – If True, return daily means seasonal cycle

  • seasonalmonth (bool, optional) – Same as meanmonth. If True, return mean monthly cycle

  • seasonalmeanday (bool, optional) – If True, return one mean daily cycle per month

  • sum (bool, optional) – If True, calculate sums instead of means

  • max (bool, optional) – If True, calculate maxima instead of means

  • min (bool, optional) – If True, calculate minima instead of means

  • onlydat (bool, optional) – If True, return only meandat, else return [outdate, meandat]

  • **kwargs (dict, optional) – Any other keyword argument will be passed to either pyjams.date2num or pyjams.num2date depending on type of date

Returns:

centred date on year, month, day, etc.; and averaged data in 1st dimension

Return type:

outdate, meandat

Notes

outdate is same format as date input. Output meandat is scalar, numpy array, or masked array if needed.

Returns centred [dates, averages]:
  • Yearly dates are centred on June 15, 12:00 h

  • Monthly dates are centred on 15th, 12:00 h

  • Daily dates are centred on 12:00 h

  • Hourly dates are centred on 30 min

  • Half hourly dates are centred on 15 and 45 min

  • Minute dates are centred on 30 sec

  • Mean daily dates are centred on 30 min of January 01 of the first year

  • Mean monthly (seasonal monthly) dates are centred on the 15th of each month at 12:00 h of the first year

  • Seasonal daily dates are centred on 12:00 h of each day of the first (leap) year

  • Seasonal mean daily dates are centred on 30 min of each first day of each month of the first year

If meanday/seasonal/meanday/seasonalday/meanmonth/seasonalmonth==True, then all hours/months/days will be written; as a masked-array if hours/days/months are missing.

If seasonalday==True, input data has to be spaced <= days, otherwise consider meanmonth/seasonalmonth.

If input date represent the beginning/end of the time step, the user should add/remove half a time step before using the routine. Otherwise the routine would have to guess the time step, which is error prone. For example, remove 15 minutes by subtracting datetime.timedelta(minutes=15) from datetime, 15./(24.*60.) from Julian dates, or pyjams.date2num(‘2010-01-01 12:15’, units, calendar) - pyjams.date2num(‘2010-01-01 12:00’, units, calendar) from any calendar and units understood by pyjams.datetime or cftime.datetime.

Examples

>>> dates = ['01.01.1990 12:00:00', '01.02.1990 12:00:00',
...          '01.03.1990 12:00:00', '01.01.1990 12:10:00',
...          '01.01.1990 13:00:00', '01.01.1990 14:00:00']
>>> jdates = date2num(dates, calendar='decimal')
>>> x = np.arange(len(jdates)) + 1.
>>> odates, xout = means(jdates, x, calendar='decimal')
>>> oodates = num2date(odates, calendar='decimal')
>>> oodates = oodates.strftime('%Y-%m-%d %H:%M:%S')
>>> print(oodates, xout)
1990-01-31 00:00:00 3.5
>>> odates, xout = means(jdates, x, year=True, calendar='decimal')
>>> print(xout)
[3.5]
>>> odates, xout = means(dates, x, month=True)
>>> print(xout)
[4. 2. 3.]
>>> odates, xout = means(dates, x, day=True)
>>> print(xout)
[4. 2. 3.]
>>> odates, xout = means(dates, x, hour=True)
>>> print(xout)
[2.5 5.  6.  2.  3. ]
>>> odates, xout = means(jdates, x, half_hour=True, calendar='decimal')
>>> print(xout)
[2.5 5.  6.  2.  3. ]
>>> odates, xout = means(jdates, x, meanday=True, calendar='decimal')
>>> print(xout[10:16])
[-- -- 2.5 5.0 6.0 --]
>>> odates, xout = means(jdates, x, meanmonth=True, calendar='decimal')
>>> print(xout[0:5])
[4.0 2.0 3.0 --  --]
>>> odates, xout = means(jdates, x, seasonalday=True, calendar='decimal')
>>> print(xout[0:5])
[4.0 -- -- -- --]
>>> odates, xout = means(jdates, x, seasonalmonth=True, calendar='decimal')
>>> print(xout[0:5])
[4.0 2.0 3.0 --  --]
>>> print(means(jdates, x, month=True, onlydat=True, calendar='decimal'))
[4. 2. 3.]

Masked arrays

>>> x = np.ma.array(x, mask=np.zeros(x.size, dtype=bool))
>>> x.mask[0] = True
>>> odates, xout = means(jdates, x, calendar='decimal')
>>> print(np.around(odates, 1), xout)
1990.1 4.0
>>> odates, xout = means(dates, x, year=True)
>>> print(xout)
[4.0]
>>> odates, xout = means(dates, x, month=True)
>>> print(xout)
[5.0 2.0 3.0]
>>> odates, xout = means(jdates, x, day=True, calendar='decimal')
>>> print(xout)
[5.0 2.0 3.0]

sum

>>> odates, xout = means(jdates, x, sum=True, calendar='decimal')
>>> print(np.around(odates, 1), xout)
1990.1 20.0
>>> odates, xout = means(jdates, x, year=True, sum=True,
...                      calendar='decimal')
>>> print(xout)
[20.0]
>>> odates, xout = means(dates, x, month=True, sum=True)
>>> print(xout)
[15.0 2.0 3.0]
>>> odates, xout = means(jdates, x, day=True, sum=True, calendar='decimal')
>>> print(xout)
[15.0 2.0 3.0]

max

>>> odates, xout = means(jdates, x, max=True, calendar='decimal')
>>> print(np.around(odates, 1), xout)
1990.1 6.0
>>> odates, xout = means(dates, x, year=True, max=True)
>>> print(xout)
[6.0]
>>> odates, xout = means(jdates, x, month=True, max=True,
...                      calendar='decimal')
>>> print(xout)
[6.0 2.0 3.0]
>>> odates, xout = means(jdates, x, day=True, max=True, calendar='decimal')
>>> print(xout)
[6.0 2.0 3.0]

min

>>> odates, xout = means(jdates, x, min=True, calendar='decimal')
>>> print(np.around(odates, 1), xout)
1990.1 2.0
>>> odates, xout = means(jdates, x, year=True, min=True,
...                      calendar='decimal')
>>> print(xout)
[2.0]
>>> odates, xout = means(dates, x, month=True, min=True)
>>> print(xout)
[4.0 2.0 3.0]
>>> odates, xout = means(jdates, x, day=True, min=True, calendar='decimal')
>>> print(xout)
[4.0 2.0 3.0]

2D and masked arrays

>>> x  = np.repeat(x,2).reshape((x.size,2))
>>> odates, xout = means(jdates, x, calendar='decimal')
>>> print(np.around(odates, 1), xout)
1990.1 [4.0 4.0]
>>> odates, xout = means(jdates, x, year=True, calendar='decimal')
>>> print(xout)
[[4.0 4.0]]
>>> odates, xout = means(dates, x, month=True)
>>> print(xout)
[[5.0 5.0]
 [2.0 2.0]
 [3.0 3.0]]
>>> odates, xout = means(jdates, x, day=True, calendar='decimal')
>>> print(xout)
[[5.0 5.0]
 [2.0 2.0]
 [3.0 3.0]]