Search code examples
pythonpandasnumpypython-xarraypint

How to convert numpy.timedelta64 to a pint quantity object with a time unit?


I need to convert a power time series (MW) to energy (MWh) by taking the sum:

import pint
import xarray as xr
import pandas as pd

ureg = pint.UnitRegistry()

power_mw = xr.DataArray(
    np.random.random(365*24),
    dims='time',
    coords={'time': pd.date_range('2023', freq='h', periods=365*24)}
)

power = power_mw * ureg.MW

In this example power is the average power generation (e.g. of a wind turbine) for each hour in a year. If we want to get the total energy we need to multiply by the interval length and sum up:

>>> (power * ureg.h).sum()
<xarray.DataArray ()> Size: 8B
<Quantity(4375.12491, 'hour * megawatt')>

This works, but it would be nice to use the time coordinates somehow:

>>> power.time.diff(dim='time')[0]
<xarray.DataArray 'time' ()> Size: 8B
array(3600000000000, dtype='timedelta64[ns]')
Coordinates:
    time     datetime64[ns] 8B 2024-01-01T01:00:00

What is the best way to translate the datetime64 object to a pint quantity?


Solution

  • The best way I came up with is this:

    interval_lengths = power.time.diff(dim='time')
    
    # let's assume we have equidistant time steps because otherwise it's
    # pretty unclear how to define the last (or the first) interval length...
    assert (interval_lengths == interval_lengths[0]).all()
    
    # this is the pint quantity we need
    interval_length = interval_lengths[0].values / np.timedelta64(1, "h") * ureg.h
    

    See also this Q&A.