-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add support for CFTimeIndex in get_clean_interp_index #3631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 23 commits
d5c2242
77bb24c
03e7769
e169cf4
303020f
210fb94
1cfe72d
4964163
83f6c89
6298953
3d23ccf
2ba1803
9a648d9
e873da2
532756d
73d8729
4288780
077145e
758d81c
d0d8bfe
6c9630a
d18c775
78e17ec
6615c97
2df2b29
31f5417
2974af9
eeb5074
6b9631f
5656fdb
dcf98ff
4842a96
6dbf225
c90dc97
71fb87d
3d9f333
b04785c
d24cae4
6f0c504
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| import inspect | ||
| import warnings | ||
| from functools import partial | ||
| from distutils.version import LooseVersion | ||
|
|
||
| import numpy as np | ||
| import pandas as pd | ||
|
|
@@ -372,51 +373,137 @@ def _datetime_nanmin(array): | |
|
|
||
|
|
||
| def datetime_to_numeric(array, offset=None, datetime_unit=None, dtype=float): | ||
| """Convert an array containing datetime-like data to an array of floats. | ||
| """Convert an array containing datetime-like data to numerical values. | ||
|
|
||
| Convert the datetime array to a timedelta relative to an offset. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| da : np.array | ||
| Input data | ||
| offset: Scalar with the same type of array or None | ||
| If None, subtract minimum values to reduce round off error | ||
| datetime_unit: None or any of {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', | ||
| 'us', 'ns', 'ps', 'fs', 'as'} | ||
| dtype: target dtype | ||
| da : array-like | ||
| Input data | ||
| offset: None, datetime or cftime.datetime | ||
| Datetime offset. If None, this is set by default to the array's minimum | ||
| value to reduce round off errors. | ||
| datetime_unit: {None, Y, M, W, D, h, m, s, ms, us, ns, ps, fs, as} | ||
| If not None, convert output to a given datetime unit. Note that some | ||
| conversions are not allowed due to non-linear relationships between units. | ||
| dtype: dtype | ||
| Output dtype. | ||
|
|
||
| Returns | ||
| ------- | ||
| array | ||
| Numerical representation of datetime object relative to an offset. | ||
|
|
||
| Notes | ||
| ----- | ||
| Some datetime unit conversions won't work, for example from days to years, even | ||
| though some calendars would allow for them (e.g. no_leap). This is because there | ||
| is no `cftime.timedelta` object. | ||
| """ | ||
| # TODO: make this function dask-compatible? | ||
| # Set offset to minimum if not given | ||
| if offset is None: | ||
| if array.dtype.kind in "Mm": | ||
| offset = _datetime_nanmin(array) | ||
| else: | ||
| offset = min(array) | ||
|
|
||
| # Compute timedelta object. | ||
| # For np.datetime64, this can silently yield garbage due to overflow. | ||
| # One option is to enforce 1970-01-01 as the universal offset. | ||
huard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| array = array - offset | ||
|
|
||
| if not hasattr(array, "dtype"): # scalar is converted to 0d-array | ||
| # Scalar is converted to 0d-array | ||
| if not hasattr(array, "dtype"): | ||
| array = np.array(array) | ||
|
|
||
| # Convert timedelta objects to float by first converting to microseconds. | ||
| if array.dtype.kind in "O": | ||
| # possibly convert object array containing datetime.timedelta | ||
| array = np.asarray(pd.Series(array.ravel())).reshape(array.shape) | ||
| return py_timedelta_to_float(array, datetime_unit or "ns").astype(dtype) | ||
|
|
||
| if datetime_unit: | ||
| array = array / np.timedelta64(1, datetime_unit) | ||
| # Convert np.NaT to np.nan | ||
| elif array.dtype.kind in "mM": | ||
|
|
||
| # convert np.NaT to np.nan | ||
| if array.dtype.kind in "mM": | ||
| # Convert to specified timedelta units. | ||
| if datetime_unit: | ||
| array = array / np.timedelta64(1, datetime_unit) | ||
| return np.where(isnull(array), np.nan, array.astype(dtype)) | ||
| return array.astype(dtype) | ||
|
|
||
|
|
||
| def timedelta_to_numeric(array, datetime_unit="ns", dtype=float): | ||
| """Convert an array containing timedelta-like data to numerical values. | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """ | ||
| import datetime as dt | ||
|
|
||
| if isinstance(array, dt.timedelta): | ||
| out = py_timedelta_to_float(array, datetime_unit) | ||
| elif isinstance(array, np.timedelta64): | ||
| out = np_timedelta64_to_float(array, datetime_unit) | ||
| elif isinstance(array, pd.Timedelta): | ||
| out = pd_timedelta_to_float(array, datetime_unit) | ||
| elif isinstance(array, pd.TimedeltaIndex): | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| out = pd_timedeltaindex_to_float(array, datetime_unit) | ||
| elif isinstance(array, str): | ||
| try: | ||
| a = pd.to_timedelta(array) | ||
| except ValueError: | ||
| raise ValueError( | ||
| f"Could not convert {array!r} to timedelta64 using pandas.to_timedelta" | ||
| ) | ||
| return py_timedelta_to_float(a, datetime_unit) | ||
| else: | ||
| raise TypeError( | ||
| f"Expected array of type str, pandas.Timedelta, pandas.TimedeltaIndex, " | ||
| f"datetime.timedelta or numpy.timedelta64, but received {type(array).__name__}" | ||
| ) | ||
| return out.astype(dtype) | ||
|
|
||
|
|
||
| def _to_pytimedelta(array, unit="us"): | ||
| index = pd.TimedeltaIndex(array.ravel(), unit=unit) | ||
| return index.to_pytimedelta().reshape(array.shape) | ||
|
|
||
|
|
||
| def np_timedelta64_to_float(array, datetime_unit): | ||
huard marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| array = array.astype("timedelta64[us]") | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| conversion_factor = np.timedelta64(1, "us") / np.timedelta64(1, datetime_unit) | ||
| return conversion_factor * array | ||
|
|
||
|
|
||
| def pd_timedelta_to_float(array, datetime_units): | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| array = np.timedelta64(array.value, "ns").astype(np.float64) | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return np_timedelta64_to_float(array, datetime_units) | ||
|
|
||
|
|
||
| def pd_timedeltaindex_to_float(array, datetime_units): | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return np_timedelta64_to_float(array.values, datetime_units) | ||
|
|
||
|
|
||
| def py_timedelta_to_float(array, datetime_unit): | ||
| """Convert a timedelta object to a float, possibly at a loss of resolution. | ||
|
|
||
| Notes | ||
| ----- | ||
| With Numpy >= 1.17, it's possible to convert directly from `datetime.timedelta` | ||
| to `numpy.timedelta64` at the microsecond (us) resolution. This covers a fairly | ||
| large span of years. | ||
|
|
||
| With earlier Numpy versions, the conversion only works at the nanosecond resolution, | ||
spencerkclark marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| which restricts the span that can be covered. | ||
| """ | ||
| if LooseVersion(np.__version__) < LooseVersion("1.17"): | ||
| array = np.asarray(array) | ||
| array = ( | ||
| np.reshape([a.total_seconds() for a in array.ravel()], array.shape) * 1e6 | ||
huard marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ) | ||
| else: | ||
| array = np.asarray(array).astype("timedelta64[us]").astype(np.float64) # [us] | ||
|
||
|
|
||
| conversion_factor = np.timedelta64(1, "us") / np.timedelta64(1, datetime_unit) | ||
| return conversion_factor * array | ||
|
|
||
|
|
||
| def mean(array, axis=None, skipna=None, **kwargs): | ||
| """inhouse mean that can handle np.datetime64 or cftime.datetime | ||
| dtypes""" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.