8th day of python challenges 111-117
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
from datetime import timedelta
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas.errors import NullFrequencyError
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Timedelta, TimedeltaIndex, timedelta_range
|
||||
import pandas.util.testing as tm
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
pd.offsets.Hour(2),
|
||||
timedelta(hours=2),
|
||||
np.timedelta64(2, "h"),
|
||||
Timedelta(hours=2),
|
||||
],
|
||||
ids=str,
|
||||
)
|
||||
def delta(request):
|
||||
# Several ways of representing two hours
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(params=["B", "D"])
|
||||
def freq(request):
|
||||
return request.param
|
||||
|
||||
|
||||
class TestTimedeltaIndexArithmetic:
|
||||
# Addition and Subtraction Operations
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# TimedeltaIndex.shift is used by __add__/__sub__
|
||||
|
||||
def test_tdi_shift_empty(self):
|
||||
# GH#9903
|
||||
idx = pd.TimedeltaIndex([], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(0, freq="H"), idx)
|
||||
tm.assert_index_equal(idx.shift(3, freq="H"), idx)
|
||||
|
||||
def test_tdi_shift_hours(self):
|
||||
# GH#9903
|
||||
idx = pd.TimedeltaIndex(["5 hours", "6 hours", "9 hours"], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(0, freq="H"), idx)
|
||||
exp = pd.TimedeltaIndex(["8 hours", "9 hours", "12 hours"], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(3, freq="H"), exp)
|
||||
exp = pd.TimedeltaIndex(["2 hours", "3 hours", "6 hours"], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(-3, freq="H"), exp)
|
||||
|
||||
def test_tdi_shift_minutes(self):
|
||||
# GH#9903
|
||||
idx = pd.TimedeltaIndex(["5 hours", "6 hours", "9 hours"], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(0, freq="T"), idx)
|
||||
exp = pd.TimedeltaIndex(["05:03:00", "06:03:00", "9:03:00"], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(3, freq="T"), exp)
|
||||
exp = pd.TimedeltaIndex(["04:57:00", "05:57:00", "8:57:00"], name="xxx")
|
||||
tm.assert_index_equal(idx.shift(-3, freq="T"), exp)
|
||||
|
||||
def test_tdi_shift_int(self):
|
||||
# GH#8083
|
||||
trange = pd.to_timedelta(range(5), unit="d") + pd.offsets.Hour(1)
|
||||
result = trange.shift(1)
|
||||
expected = TimedeltaIndex(
|
||||
[
|
||||
"1 days 01:00:00",
|
||||
"2 days 01:00:00",
|
||||
"3 days 01:00:00",
|
||||
"4 days 01:00:00",
|
||||
"5 days 01:00:00",
|
||||
],
|
||||
freq="D",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_tdi_shift_nonstandard_freq(self):
|
||||
# GH#8083
|
||||
trange = pd.to_timedelta(range(5), unit="d") + pd.offsets.Hour(1)
|
||||
result = trange.shift(3, freq="2D 1s")
|
||||
expected = TimedeltaIndex(
|
||||
[
|
||||
"6 days 01:00:03",
|
||||
"7 days 01:00:03",
|
||||
"8 days 01:00:03",
|
||||
"9 days 01:00:03",
|
||||
"10 days 01:00:03",
|
||||
],
|
||||
freq="D",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_shift_no_freq(self):
|
||||
# GH#19147
|
||||
tdi = TimedeltaIndex(["1 days 01:00:00", "2 days 01:00:00"], freq=None)
|
||||
with pytest.raises(NullFrequencyError):
|
||||
tdi.shift(2)
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Binary operations TimedeltaIndex and integer
|
||||
|
||||
def test_tdi_add_int(self, one):
|
||||
# Variants of `one` for #19012
|
||||
rng = timedelta_range("1 days 09:00:00", freq="H", periods=10)
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
result = rng + one
|
||||
expected = timedelta_range("1 days 10:00:00", freq="H", periods=10)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_tdi_iadd_int(self, one):
|
||||
rng = timedelta_range("1 days 09:00:00", freq="H", periods=10)
|
||||
expected = timedelta_range("1 days 10:00:00", freq="H", periods=10)
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
rng += one
|
||||
tm.assert_index_equal(rng, expected)
|
||||
|
||||
def test_tdi_sub_int(self, one):
|
||||
rng = timedelta_range("1 days 09:00:00", freq="H", periods=10)
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
result = rng - one
|
||||
expected = timedelta_range("1 days 08:00:00", freq="H", periods=10)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_tdi_isub_int(self, one):
|
||||
rng = timedelta_range("1 days 09:00:00", freq="H", periods=10)
|
||||
expected = timedelta_range("1 days 08:00:00", freq="H", periods=10)
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
rng -= one
|
||||
tm.assert_index_equal(rng, expected)
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# __add__/__sub__ with integer arrays
|
||||
|
||||
@pytest.mark.parametrize("box", [np.array, pd.Index])
|
||||
def test_tdi_add_integer_array(self, box):
|
||||
# GH#19959
|
||||
rng = timedelta_range("1 days 09:00:00", freq="H", periods=3)
|
||||
other = box([4, 3, 2])
|
||||
expected = TimedeltaIndex(["1 day 13:00:00"] * 3)
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
result = rng + other
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
result = other + rng
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("box", [np.array, pd.Index])
|
||||
def test_tdi_sub_integer_array(self, box):
|
||||
# GH#19959
|
||||
rng = timedelta_range("9H", freq="H", periods=3)
|
||||
other = box([4, 3, 2])
|
||||
expected = TimedeltaIndex(["5H", "7H", "9H"])
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
result = rng - other
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
# GH#22535
|
||||
result = other - rng
|
||||
tm.assert_index_equal(result, -expected)
|
||||
|
||||
@pytest.mark.parametrize("box", [np.array, pd.Index])
|
||||
def test_tdi_addsub_integer_array_no_freq(self, box):
|
||||
# GH#19959
|
||||
tdi = TimedeltaIndex(["1 Day", "NaT", "3 Hours"])
|
||||
other = box([14, -1, 16])
|
||||
with pytest.raises(NullFrequencyError):
|
||||
tdi + other
|
||||
with pytest.raises(NullFrequencyError):
|
||||
other + tdi
|
||||
with pytest.raises(NullFrequencyError):
|
||||
tdi - other
|
||||
with pytest.raises(NullFrequencyError):
|
||||
other - tdi
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Binary operations TimedeltaIndex and timedelta-like
|
||||
# Note: add and sub are tested in tests.test_arithmetic, in-place
|
||||
# tests are kept here because their behavior is Index-specific
|
||||
|
||||
def test_tdi_iadd_timedeltalike(self, delta):
|
||||
# only test adding/sub offsets as + is now numeric
|
||||
rng = timedelta_range("1 days", "10 days")
|
||||
expected = timedelta_range("1 days 02:00:00", "10 days 02:00:00", freq="D")
|
||||
rng += delta
|
||||
tm.assert_index_equal(rng, expected)
|
||||
|
||||
def test_tdi_isub_timedeltalike(self, delta):
|
||||
# only test adding/sub offsets as - is now numeric
|
||||
rng = timedelta_range("1 days", "10 days")
|
||||
expected = timedelta_range("0 days 22:00:00", "9 days 22:00:00")
|
||||
rng -= delta
|
||||
tm.assert_index_equal(rng, expected)
|
||||
|
||||
# -------------------------------------------------------------
|
||||
|
||||
# TODO: after #24365 this probably belongs in scalar tests
|
||||
def test_ops_ndarray(self):
|
||||
td = Timedelta("1 day")
|
||||
|
||||
# timedelta, timedelta
|
||||
other = pd.to_timedelta(["1 day"]).values
|
||||
expected = pd.to_timedelta(["2 days"]).values
|
||||
tm.assert_numpy_array_equal(td + other, expected)
|
||||
tm.assert_numpy_array_equal(other + td, expected)
|
||||
msg = r"unsupported operand type\(s\) for \+: 'Timedelta' and 'int'"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
td + np.array([1])
|
||||
msg = r"unsupported operand type\(s\) for \+: 'numpy.ndarray' and 'Timedelta'"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
np.array([1]) + td
|
||||
|
||||
expected = pd.to_timedelta(["0 days"]).values
|
||||
tm.assert_numpy_array_equal(td - other, expected)
|
||||
tm.assert_numpy_array_equal(-other + td, expected)
|
||||
msg = r"unsupported operand type\(s\) for -: 'Timedelta' and 'int'"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
td - np.array([1])
|
||||
msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timedelta'"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
np.array([1]) - td
|
||||
|
||||
expected = pd.to_timedelta(["2 days"]).values
|
||||
tm.assert_numpy_array_equal(td * np.array([2]), expected)
|
||||
tm.assert_numpy_array_equal(np.array([2]) * td, expected)
|
||||
msg = (
|
||||
"ufunc '?multiply'? cannot use operands with types"
|
||||
r" dtype\('<m8\[ns\]'\) and dtype\('<m8\[ns\]'\)"
|
||||
)
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
td * other
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
other * td
|
||||
|
||||
tm.assert_numpy_array_equal(td / other, np.array([1], dtype=np.float64))
|
||||
tm.assert_numpy_array_equal(other / td, np.array([1], dtype=np.float64))
|
||||
|
||||
# timedelta, datetime
|
||||
other = pd.to_datetime(["2000-01-01"]).values
|
||||
expected = pd.to_datetime(["2000-01-02"]).values
|
||||
tm.assert_numpy_array_equal(td + other, expected)
|
||||
tm.assert_numpy_array_equal(other + td, expected)
|
||||
|
||||
expected = pd.to_datetime(["1999-12-31"]).values
|
||||
tm.assert_numpy_array_equal(-td + other, expected)
|
||||
tm.assert_numpy_array_equal(other - td, expected)
|
||||
|
||||
def test_tdi_ops_attributes(self):
|
||||
rng = timedelta_range("2 days", periods=5, freq="2D", name="x")
|
||||
|
||||
result = rng + 1 * rng.freq
|
||||
exp = timedelta_range("4 days", periods=5, freq="2D", name="x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == "2D"
|
||||
|
||||
result = rng - 2 * rng.freq
|
||||
exp = timedelta_range("-2 days", periods=5, freq="2D", name="x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == "2D"
|
||||
|
||||
result = rng * 2
|
||||
exp = timedelta_range("4 days", periods=5, freq="4D", name="x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == "4D"
|
||||
|
||||
result = rng / 2
|
||||
exp = timedelta_range("1 days", periods=5, freq="D", name="x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == "D"
|
||||
|
||||
result = -rng
|
||||
exp = timedelta_range("-2 days", periods=5, freq="-2D", name="x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == "-2D"
|
||||
|
||||
rng = pd.timedelta_range("-2 days", periods=5, freq="D", name="x")
|
||||
|
||||
result = abs(rng)
|
||||
exp = TimedeltaIndex(
|
||||
["2 days", "1 days", "0 days", "1 days", "2 days"], name="x"
|
||||
)
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq is None
|
@@ -0,0 +1,123 @@
|
||||
from datetime import timedelta
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
Float64Index,
|
||||
Index,
|
||||
Int64Index,
|
||||
NaT,
|
||||
Timedelta,
|
||||
TimedeltaIndex,
|
||||
timedelta_range,
|
||||
)
|
||||
import pandas.util.testing as tm
|
||||
|
||||
|
||||
class TestTimedeltaIndex:
|
||||
def test_astype_object(self):
|
||||
idx = timedelta_range(start="1 days", periods=4, freq="D", name="idx")
|
||||
expected_list = [
|
||||
Timedelta("1 days"),
|
||||
Timedelta("2 days"),
|
||||
Timedelta("3 days"),
|
||||
Timedelta("4 days"),
|
||||
]
|
||||
result = idx.astype(object)
|
||||
expected = Index(expected_list, dtype=object, name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert idx.tolist() == expected_list
|
||||
|
||||
def test_astype_object_with_nat(self):
|
||||
idx = TimedeltaIndex(
|
||||
[timedelta(days=1), timedelta(days=2), NaT, timedelta(days=4)], name="idx"
|
||||
)
|
||||
expected_list = [
|
||||
Timedelta("1 days"),
|
||||
Timedelta("2 days"),
|
||||
NaT,
|
||||
Timedelta("4 days"),
|
||||
]
|
||||
result = idx.astype(object)
|
||||
expected = Index(expected_list, dtype=object, name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert idx.tolist() == expected_list
|
||||
|
||||
def test_astype(self):
|
||||
# GH 13149, GH 13209
|
||||
idx = TimedeltaIndex([1e14, "NaT", NaT, np.NaN])
|
||||
|
||||
result = idx.astype(object)
|
||||
expected = Index([Timedelta("1 days 03:46:40")] + [NaT] * 3, dtype=object)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.astype(int)
|
||||
expected = Int64Index(
|
||||
[100000000000000] + [-9223372036854775808] * 3, dtype=np.int64
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.astype(str)
|
||||
expected = Index(str(x) for x in idx)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
rng = timedelta_range("1 days", periods=10)
|
||||
result = rng.astype("i8")
|
||||
tm.assert_index_equal(result, Index(rng.asi8))
|
||||
tm.assert_numpy_array_equal(rng.asi8, result.values)
|
||||
|
||||
def test_astype_uint(self):
|
||||
arr = timedelta_range("1H", periods=2)
|
||||
expected = pd.UInt64Index(
|
||||
np.array([3600000000000, 90000000000000], dtype="uint64")
|
||||
)
|
||||
|
||||
tm.assert_index_equal(arr.astype("uint64"), expected)
|
||||
tm.assert_index_equal(arr.astype("uint32"), expected)
|
||||
|
||||
def test_astype_timedelta64(self):
|
||||
# GH 13149, GH 13209
|
||||
idx = TimedeltaIndex([1e14, "NaT", NaT, np.NaN])
|
||||
|
||||
result = idx.astype("timedelta64")
|
||||
expected = Float64Index([1e14] + [np.NaN] * 3, dtype="float64")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.astype("timedelta64[ns]")
|
||||
tm.assert_index_equal(result, idx)
|
||||
assert result is not idx
|
||||
|
||||
result = idx.astype("timedelta64[ns]", copy=False)
|
||||
tm.assert_index_equal(result, idx)
|
||||
assert result is idx
|
||||
|
||||
@pytest.mark.parametrize("dtype", [float, "datetime64", "datetime64[ns]"])
|
||||
def test_astype_raises(self, dtype):
|
||||
# GH 13149, GH 13209
|
||||
idx = TimedeltaIndex([1e14, "NaT", NaT, np.NaN])
|
||||
msg = "Cannot cast TimedeltaArray to dtype"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx.astype(dtype)
|
||||
|
||||
def test_astype_category(self):
|
||||
obj = pd.timedelta_range("1H", periods=2, freq="H")
|
||||
|
||||
result = obj.astype("category")
|
||||
expected = pd.CategoricalIndex([pd.Timedelta("1H"), pd.Timedelta("2H")])
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = obj._data.astype("category")
|
||||
expected = expected.values
|
||||
tm.assert_categorical_equal(result, expected)
|
||||
|
||||
def test_astype_array_fallback(self):
|
||||
obj = pd.timedelta_range("1H", periods=2)
|
||||
result = obj.astype(bool)
|
||||
expected = pd.Index(np.array([True, True]))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = obj._data.astype(bool)
|
||||
expected = np.array([True, True])
|
||||
tm.assert_numpy_array_equal(result, expected)
|
@@ -0,0 +1,229 @@
|
||||
from datetime import timedelta
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Timedelta, TimedeltaIndex, timedelta_range, to_timedelta
|
||||
from pandas.core.arrays import TimedeltaArray
|
||||
import pandas.util.testing as tm
|
||||
|
||||
|
||||
class TestTimedeltaIndex:
|
||||
def test_verify_integrity_deprecated(self):
|
||||
# GH#23919
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
TimedeltaIndex(["1 Day"], verify_integrity=False)
|
||||
|
||||
def test_range_kwargs_deprecated(self):
|
||||
# GH#23919
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
TimedeltaIndex(start="1 Day", end="3 Days", freq="D")
|
||||
|
||||
def test_int64_nocopy(self):
|
||||
# GH#23539 check that a copy isn't made when we pass int64 data
|
||||
# and copy=False
|
||||
arr = np.arange(10, dtype=np.int64)
|
||||
tdi = TimedeltaIndex(arr, copy=False)
|
||||
assert tdi._data._data.base is arr
|
||||
|
||||
def test_infer_from_tdi(self):
|
||||
# GH#23539
|
||||
# fast-path for inferring a frequency if the passed data already
|
||||
# has one
|
||||
tdi = pd.timedelta_range("1 second", periods=10 ** 7, freq="1s")
|
||||
|
||||
result = pd.TimedeltaIndex(tdi, freq="infer")
|
||||
assert result.freq == tdi.freq
|
||||
|
||||
# check that inferred_freq was not called by checking that the
|
||||
# value has not been cached
|
||||
assert "inferred_freq" not in getattr(result, "_cache", {})
|
||||
|
||||
def test_infer_from_tdi_mismatch(self):
|
||||
# GH#23539
|
||||
# fast-path for invalidating a frequency if the passed data already
|
||||
# has one and it does not match the `freq` input
|
||||
tdi = pd.timedelta_range("1 second", periods=100, freq="1s")
|
||||
|
||||
msg = (
|
||||
"Inferred frequency .* from passed values does "
|
||||
"not conform to passed frequency"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
TimedeltaIndex(tdi, freq="D")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
# GH#23789
|
||||
TimedeltaArray(tdi, freq="D")
|
||||
|
||||
def test_dt64_data_invalid(self):
|
||||
# GH#23539
|
||||
# passing tz-aware DatetimeIndex raises, naive or ndarray[datetime64]
|
||||
# does not yet, but will in the future
|
||||
dti = pd.date_range("2016-01-01", periods=3)
|
||||
|
||||
msg = "cannot be converted to timedelta64"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
TimedeltaIndex(dti.tz_localize("Europe/Brussels"))
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
TimedeltaIndex(dti)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
TimedeltaIndex(np.asarray(dti))
|
||||
|
||||
def test_float64_ns_rounded(self):
|
||||
# GH#23539 without specifying a unit, floats are regarded as nanos,
|
||||
# and fractional portions are truncated
|
||||
tdi = TimedeltaIndex([2.3, 9.7])
|
||||
expected = TimedeltaIndex([2, 9])
|
||||
tm.assert_index_equal(tdi, expected)
|
||||
|
||||
# integral floats are non-lossy
|
||||
tdi = TimedeltaIndex([2.0, 9.0])
|
||||
expected = TimedeltaIndex([2, 9])
|
||||
tm.assert_index_equal(tdi, expected)
|
||||
|
||||
# NaNs get converted to NaT
|
||||
tdi = TimedeltaIndex([2.0, np.nan])
|
||||
expected = TimedeltaIndex([pd.Timedelta(nanoseconds=2), pd.NaT])
|
||||
tm.assert_index_equal(tdi, expected)
|
||||
|
||||
def test_float64_unit_conversion(self):
|
||||
# GH#23539
|
||||
tdi = TimedeltaIndex([1.5, 2.25], unit="D")
|
||||
expected = TimedeltaIndex([Timedelta(days=1.5), Timedelta(days=2.25)])
|
||||
tm.assert_index_equal(tdi, expected)
|
||||
|
||||
def test_construction_base_constructor(self):
|
||||
arr = [pd.Timedelta("1 days"), pd.NaT, pd.Timedelta("3 days")]
|
||||
tm.assert_index_equal(pd.Index(arr), pd.TimedeltaIndex(arr))
|
||||
tm.assert_index_equal(pd.Index(np.array(arr)), pd.TimedeltaIndex(np.array(arr)))
|
||||
|
||||
arr = [np.nan, pd.NaT, pd.Timedelta("1 days")]
|
||||
tm.assert_index_equal(pd.Index(arr), pd.TimedeltaIndex(arr))
|
||||
tm.assert_index_equal(pd.Index(np.array(arr)), pd.TimedeltaIndex(np.array(arr)))
|
||||
|
||||
def test_constructor(self):
|
||||
expected = TimedeltaIndex(
|
||||
[
|
||||
"1 days",
|
||||
"1 days 00:00:05",
|
||||
"2 days",
|
||||
"2 days 00:00:02",
|
||||
"0 days 00:00:03",
|
||||
]
|
||||
)
|
||||
result = TimedeltaIndex(
|
||||
[
|
||||
"1 days",
|
||||
"1 days, 00:00:05",
|
||||
np.timedelta64(2, "D"),
|
||||
timedelta(days=2, seconds=2),
|
||||
pd.offsets.Second(3),
|
||||
]
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# unicode
|
||||
result = TimedeltaIndex(
|
||||
[
|
||||
"1 days",
|
||||
"1 days, 00:00:05",
|
||||
np.timedelta64(2, "D"),
|
||||
timedelta(days=2, seconds=2),
|
||||
pd.offsets.Second(3),
|
||||
]
|
||||
)
|
||||
|
||||
expected = TimedeltaIndex(
|
||||
["0 days 00:00:00", "0 days 00:00:01", "0 days 00:00:02"]
|
||||
)
|
||||
tm.assert_index_equal(TimedeltaIndex(range(3), unit="s"), expected)
|
||||
expected = TimedeltaIndex(
|
||||
["0 days 00:00:00", "0 days 00:00:05", "0 days 00:00:09"]
|
||||
)
|
||||
tm.assert_index_equal(TimedeltaIndex([0, 5, 9], unit="s"), expected)
|
||||
expected = TimedeltaIndex(
|
||||
["0 days 00:00:00.400", "0 days 00:00:00.450", "0 days 00:00:01.200"]
|
||||
)
|
||||
tm.assert_index_equal(TimedeltaIndex([400, 450, 1200], unit="ms"), expected)
|
||||
|
||||
def test_constructor_iso(self):
|
||||
# GH #21877
|
||||
expected = timedelta_range("1s", periods=9, freq="s")
|
||||
durations = ["P0DT0H0M{}S".format(i) for i in range(1, 10)]
|
||||
result = to_timedelta(durations)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_constructor_coverage(self):
|
||||
rng = timedelta_range("1 days", periods=10.5)
|
||||
exp = timedelta_range("1 days", periods=10)
|
||||
tm.assert_index_equal(rng, exp)
|
||||
|
||||
msg = "periods must be a number, got foo"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
timedelta_range(start="1 days", periods="foo", freq="D")
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
TimedeltaIndex(start="1 days", end="10 days")
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
TimedeltaIndex("1 days")
|
||||
|
||||
# generator expression
|
||||
gen = (timedelta(i) for i in range(10))
|
||||
result = TimedeltaIndex(gen)
|
||||
expected = TimedeltaIndex([timedelta(i) for i in range(10)])
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# NumPy string array
|
||||
strings = np.array(["1 days", "2 days", "3 days"])
|
||||
result = TimedeltaIndex(strings)
|
||||
expected = to_timedelta([1, 2, 3], unit="d")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
from_ints = TimedeltaIndex(expected.asi8)
|
||||
tm.assert_index_equal(from_ints, expected)
|
||||
|
||||
# non-conforming freq
|
||||
msg = (
|
||||
"Inferred frequency None from passed values does not conform to"
|
||||
" passed frequency D"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
TimedeltaIndex(["1 days", "2 days", "4 days"], freq="D")
|
||||
|
||||
msg = (
|
||||
"Of the four parameters: start, end, periods, and freq, exactly"
|
||||
" three must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
timedelta_range(periods=10, freq="D")
|
||||
|
||||
def test_constructor_name(self):
|
||||
idx = timedelta_range(start="1 days", periods=1, freq="D", name="TEST")
|
||||
assert idx.name == "TEST"
|
||||
|
||||
# GH10025
|
||||
idx2 = TimedeltaIndex(idx, name="something else")
|
||||
assert idx2.name == "something else"
|
||||
|
||||
def test_constructor_no_precision_warns(self):
|
||||
# GH-24753, GH-24739
|
||||
expected = pd.TimedeltaIndex(["2000"], dtype="timedelta64[ns]")
|
||||
|
||||
# we set the stacklevel for DatetimeIndex
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = pd.TimedeltaIndex(["2000"], dtype="timedelta64")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
|
||||
result = pd.Index(["2000"], dtype="timedelta64")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_constructor_wrong_precision_raises(self):
|
||||
with pytest.raises(ValueError):
|
||||
pd.TimedeltaIndex(["2000"], dtype="timedelta64[us]")
|
@@ -0,0 +1,90 @@
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import TimedeltaIndex
|
||||
|
||||
|
||||
class TestTimedeltaIndexRendering:
|
||||
@pytest.mark.parametrize("method", ["__repr__", "__str__"])
|
||||
def test_representation(self, method):
|
||||
idx1 = TimedeltaIndex([], freq="D")
|
||||
idx2 = TimedeltaIndex(["1 days"], freq="D")
|
||||
idx3 = TimedeltaIndex(["1 days", "2 days"], freq="D")
|
||||
idx4 = TimedeltaIndex(["1 days", "2 days", "3 days"], freq="D")
|
||||
idx5 = TimedeltaIndex(["1 days 00:00:01", "2 days", "3 days"])
|
||||
|
||||
exp1 = "TimedeltaIndex([], dtype='timedelta64[ns]', freq='D')"
|
||||
|
||||
exp2 = "TimedeltaIndex(['1 days'], dtype='timedelta64[ns]', freq='D')"
|
||||
|
||||
exp3 = "TimedeltaIndex(['1 days', '2 days'], dtype='timedelta64[ns]', freq='D')"
|
||||
|
||||
exp4 = (
|
||||
"TimedeltaIndex(['1 days', '2 days', '3 days'], "
|
||||
"dtype='timedelta64[ns]', freq='D')"
|
||||
)
|
||||
|
||||
exp5 = (
|
||||
"TimedeltaIndex(['1 days 00:00:01', '2 days 00:00:00', "
|
||||
"'3 days 00:00:00'], dtype='timedelta64[ns]', freq=None)"
|
||||
)
|
||||
|
||||
with pd.option_context("display.width", 300):
|
||||
for idx, expected in zip(
|
||||
[idx1, idx2, idx3, idx4, idx5], [exp1, exp2, exp3, exp4, exp5]
|
||||
):
|
||||
result = getattr(idx, method)()
|
||||
assert result == expected
|
||||
|
||||
def test_representation_to_series(self):
|
||||
idx1 = TimedeltaIndex([], freq="D")
|
||||
idx2 = TimedeltaIndex(["1 days"], freq="D")
|
||||
idx3 = TimedeltaIndex(["1 days", "2 days"], freq="D")
|
||||
idx4 = TimedeltaIndex(["1 days", "2 days", "3 days"], freq="D")
|
||||
idx5 = TimedeltaIndex(["1 days 00:00:01", "2 days", "3 days"])
|
||||
|
||||
exp1 = """Series([], dtype: timedelta64[ns])"""
|
||||
|
||||
exp2 = "0 1 days\ndtype: timedelta64[ns]"
|
||||
|
||||
exp3 = "0 1 days\n1 2 days\ndtype: timedelta64[ns]"
|
||||
|
||||
exp4 = "0 1 days\n1 2 days\n2 3 days\ndtype: timedelta64[ns]"
|
||||
|
||||
exp5 = (
|
||||
"0 1 days 00:00:01\n"
|
||||
"1 2 days 00:00:00\n"
|
||||
"2 3 days 00:00:00\n"
|
||||
"dtype: timedelta64[ns]"
|
||||
)
|
||||
|
||||
with pd.option_context("display.width", 300):
|
||||
for idx, expected in zip(
|
||||
[idx1, idx2, idx3, idx4, idx5], [exp1, exp2, exp3, exp4, exp5]
|
||||
):
|
||||
result = repr(pd.Series(idx))
|
||||
assert result == expected
|
||||
|
||||
def test_summary(self):
|
||||
# GH#9116
|
||||
idx1 = TimedeltaIndex([], freq="D")
|
||||
idx2 = TimedeltaIndex(["1 days"], freq="D")
|
||||
idx3 = TimedeltaIndex(["1 days", "2 days"], freq="D")
|
||||
idx4 = TimedeltaIndex(["1 days", "2 days", "3 days"], freq="D")
|
||||
idx5 = TimedeltaIndex(["1 days 00:00:01", "2 days", "3 days"])
|
||||
|
||||
exp1 = "TimedeltaIndex: 0 entries\nFreq: D"
|
||||
|
||||
exp2 = "TimedeltaIndex: 1 entries, 1 days to 1 days\nFreq: D"
|
||||
|
||||
exp3 = "TimedeltaIndex: 2 entries, 1 days to 2 days\nFreq: D"
|
||||
|
||||
exp4 = "TimedeltaIndex: 3 entries, 1 days to 3 days\nFreq: D"
|
||||
|
||||
exp5 = "TimedeltaIndex: 3 entries, 1 days 00:00:01 to 3 days 00:00:00"
|
||||
|
||||
for idx, expected in zip(
|
||||
[idx1, idx2, idx3, idx4, idx5], [exp1, exp2, exp3, exp4, exp5]
|
||||
):
|
||||
result = idx._summary()
|
||||
assert result == expected
|
@@ -0,0 +1,345 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Index, Timedelta, TimedeltaIndex, timedelta_range
|
||||
import pandas.util.testing as tm
|
||||
|
||||
|
||||
class TestGetItem:
|
||||
def test_ellipsis(self):
|
||||
# GH#21282
|
||||
idx = timedelta_range("1 day", "31 day", freq="D", name="idx")
|
||||
|
||||
result = idx[...]
|
||||
assert result.equals(idx)
|
||||
assert result is not idx
|
||||
|
||||
def test_getitem(self):
|
||||
idx1 = timedelta_range("1 day", "31 day", freq="D", name="idx")
|
||||
|
||||
for idx in [idx1]:
|
||||
result = idx[0]
|
||||
assert result == Timedelta("1 day")
|
||||
|
||||
result = idx[0:5]
|
||||
expected = timedelta_range("1 day", "5 day", freq="D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx[0:10:2]
|
||||
expected = timedelta_range("1 day", "9 day", freq="2D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx[-20:-5:3]
|
||||
expected = timedelta_range("12 day", "24 day", freq="3D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx[4::-1]
|
||||
expected = TimedeltaIndex(
|
||||
["5 day", "4 day", "3 day", "2 day", "1 day"], freq="-1D", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"key",
|
||||
[pd.Timestamp("1970-01-01"), pd.Timestamp("1970-01-02"), datetime(1970, 1, 1)],
|
||||
)
|
||||
def test_timestamp_invalid_key(self, key):
|
||||
# GH#20464
|
||||
tdi = pd.timedelta_range(0, periods=10)
|
||||
with pytest.raises(TypeError):
|
||||
tdi.get_loc(key)
|
||||
|
||||
|
||||
class TestWhere:
|
||||
# placeholder for symmetry with DatetimeIndex and PeriodIndex tests
|
||||
pass
|
||||
|
||||
|
||||
class TestTake:
|
||||
def test_take(self):
|
||||
# GH 10295
|
||||
idx1 = timedelta_range("1 day", "31 day", freq="D", name="idx")
|
||||
|
||||
for idx in [idx1]:
|
||||
result = idx.take([0])
|
||||
assert result == Timedelta("1 day")
|
||||
|
||||
result = idx.take([-1])
|
||||
assert result == Timedelta("31 day")
|
||||
|
||||
result = idx.take([0, 1, 2])
|
||||
expected = timedelta_range("1 day", "3 day", freq="D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx.take([0, 2, 4])
|
||||
expected = timedelta_range("1 day", "5 day", freq="2D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx.take([7, 4, 1])
|
||||
expected = timedelta_range("8 day", "2 day", freq="-3D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx.take([3, 2, 5])
|
||||
expected = TimedeltaIndex(["4 day", "3 day", "6 day"], name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq is None
|
||||
|
||||
result = idx.take([-3, 2, 5])
|
||||
expected = TimedeltaIndex(["29 day", "3 day", "6 day"], name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq is None
|
||||
|
||||
def test_take_invalid_kwargs(self):
|
||||
idx = timedelta_range("1 day", "31 day", freq="D", name="idx")
|
||||
indices = [1, 6, 5, 9, 10, 13, 15, 3]
|
||||
|
||||
msg = r"take\(\) got an unexpected keyword argument 'foo'"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx.take(indices, foo=2)
|
||||
|
||||
msg = "the 'out' parameter is not supported"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(indices, out=indices)
|
||||
|
||||
msg = "the 'mode' parameter is not supported"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(indices, mode="clip")
|
||||
|
||||
# TODO: This method came from test_timedelta; de-dup with version above
|
||||
def test_take2(self):
|
||||
tds = ["1day 02:00:00", "1 day 04:00:00", "1 day 10:00:00"]
|
||||
idx = timedelta_range(start="1d", end="2d", freq="H", name="idx")
|
||||
expected = TimedeltaIndex(tds, freq=None, name="idx")
|
||||
|
||||
taken1 = idx.take([2, 4, 10])
|
||||
taken2 = idx[[2, 4, 10]]
|
||||
|
||||
for taken in [taken1, taken2]:
|
||||
tm.assert_index_equal(taken, expected)
|
||||
assert isinstance(taken, TimedeltaIndex)
|
||||
assert taken.freq is None
|
||||
assert taken.name == expected.name
|
||||
|
||||
def test_take_fill_value(self):
|
||||
# GH 12631
|
||||
idx = TimedeltaIndex(["1 days", "2 days", "3 days"], name="xxx")
|
||||
result = idx.take(np.array([1, 0, -1]))
|
||||
expected = TimedeltaIndex(["2 days", "1 days", "3 days"], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# fill_value
|
||||
result = idx.take(np.array([1, 0, -1]), fill_value=True)
|
||||
expected = TimedeltaIndex(["2 days", "1 days", "NaT"], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# allow_fill=False
|
||||
result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True)
|
||||
expected = TimedeltaIndex(["2 days", "1 days", "3 days"], name="xxx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
msg = (
|
||||
"When allow_fill=True and fill_value is not None, "
|
||||
"all indices must be >= -1"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -2]), fill_value=True)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.take(np.array([1, 0, -5]), fill_value=True)
|
||||
|
||||
with pytest.raises(IndexError):
|
||||
idx.take(np.array([1, -5]))
|
||||
|
||||
|
||||
class TestTimedeltaIndex:
|
||||
def test_insert(self):
|
||||
|
||||
idx = TimedeltaIndex(["4day", "1day", "2day"], name="idx")
|
||||
|
||||
result = idx.insert(2, timedelta(days=5))
|
||||
exp = TimedeltaIndex(["4day", "1day", "5day", "2day"], name="idx")
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
# insertion of non-datetime should coerce to object index
|
||||
result = idx.insert(1, "inserted")
|
||||
expected = Index(
|
||||
[Timedelta("4day"), "inserted", Timedelta("1day"), Timedelta("2day")],
|
||||
name="idx",
|
||||
)
|
||||
assert not isinstance(result, TimedeltaIndex)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
|
||||
idx = timedelta_range("1day 00:00:01", periods=3, freq="s", name="idx")
|
||||
|
||||
# preserve freq
|
||||
expected_0 = TimedeltaIndex(
|
||||
["1day", "1day 00:00:01", "1day 00:00:02", "1day 00:00:03"],
|
||||
name="idx",
|
||||
freq="s",
|
||||
)
|
||||
expected_3 = TimedeltaIndex(
|
||||
["1day 00:00:01", "1day 00:00:02", "1day 00:00:03", "1day 00:00:04"],
|
||||
name="idx",
|
||||
freq="s",
|
||||
)
|
||||
|
||||
# reset freq to None
|
||||
expected_1_nofreq = TimedeltaIndex(
|
||||
["1day 00:00:01", "1day 00:00:01", "1day 00:00:02", "1day 00:00:03"],
|
||||
name="idx",
|
||||
freq=None,
|
||||
)
|
||||
expected_3_nofreq = TimedeltaIndex(
|
||||
["1day 00:00:01", "1day 00:00:02", "1day 00:00:03", "1day 00:00:05"],
|
||||
name="idx",
|
||||
freq=None,
|
||||
)
|
||||
|
||||
cases = [
|
||||
(0, Timedelta("1day"), expected_0),
|
||||
(-3, Timedelta("1day"), expected_0),
|
||||
(3, Timedelta("1day 00:00:04"), expected_3),
|
||||
(1, Timedelta("1day 00:00:01"), expected_1_nofreq),
|
||||
(3, Timedelta("1day 00:00:05"), expected_3_nofreq),
|
||||
]
|
||||
|
||||
for n, d, expected in cases:
|
||||
result = idx.insert(n, d)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert result.freq == expected.freq
|
||||
|
||||
# GH 18295 (test missing)
|
||||
expected = TimedeltaIndex(["1day", pd.NaT, "2day", "3day"])
|
||||
for na in (np.nan, pd.NaT, None):
|
||||
result = timedelta_range("1day", "3day").insert(1, na)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_delete(self):
|
||||
idx = timedelta_range(start="1 Days", periods=5, freq="D", name="idx")
|
||||
|
||||
# prserve freq
|
||||
expected_0 = timedelta_range(start="2 Days", periods=4, freq="D", name="idx")
|
||||
expected_4 = timedelta_range(start="1 Days", periods=4, freq="D", name="idx")
|
||||
|
||||
# reset freq to None
|
||||
expected_1 = TimedeltaIndex(
|
||||
["1 day", "3 day", "4 day", "5 day"], freq=None, name="idx"
|
||||
)
|
||||
|
||||
cases = {
|
||||
0: expected_0,
|
||||
-5: expected_0,
|
||||
-1: expected_4,
|
||||
4: expected_4,
|
||||
1: expected_1,
|
||||
}
|
||||
for n, expected in cases.items():
|
||||
result = idx.delete(n)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert result.freq == expected.freq
|
||||
|
||||
with pytest.raises((IndexError, ValueError)):
|
||||
# either depending on numpy version
|
||||
idx.delete(5)
|
||||
|
||||
def test_delete_slice(self):
|
||||
idx = timedelta_range(start="1 days", periods=10, freq="D", name="idx")
|
||||
|
||||
# prserve freq
|
||||
expected_0_2 = timedelta_range(start="4 days", periods=7, freq="D", name="idx")
|
||||
expected_7_9 = timedelta_range(start="1 days", periods=7, freq="D", name="idx")
|
||||
|
||||
# reset freq to None
|
||||
expected_3_5 = TimedeltaIndex(
|
||||
["1 d", "2 d", "3 d", "7 d", "8 d", "9 d", "10d"], freq=None, name="idx"
|
||||
)
|
||||
|
||||
cases = {
|
||||
(0, 1, 2): expected_0_2,
|
||||
(7, 8, 9): expected_7_9,
|
||||
(3, 4, 5): expected_3_5,
|
||||
}
|
||||
for n, expected in cases.items():
|
||||
result = idx.delete(n)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx.delete(slice(n[0], n[-1] + 1))
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert result.freq == expected.freq
|
||||
|
||||
def test_get_loc(self):
|
||||
idx = pd.to_timedelta(["0 days", "1 days", "2 days"])
|
||||
|
||||
for method in [None, "pad", "backfill", "nearest"]:
|
||||
assert idx.get_loc(idx[1], method) == 1
|
||||
assert idx.get_loc(idx[1].to_pytimedelta(), method) == 1
|
||||
assert idx.get_loc(str(idx[1]), method) == 1
|
||||
|
||||
assert idx.get_loc(idx[1], "pad", tolerance=Timedelta(0)) == 1
|
||||
assert idx.get_loc(idx[1], "pad", tolerance=np.timedelta64(0, "s")) == 1
|
||||
assert idx.get_loc(idx[1], "pad", tolerance=timedelta(0)) == 1
|
||||
|
||||
with pytest.raises(ValueError, match="unit abbreviation w/o a number"):
|
||||
idx.get_loc(idx[1], method="nearest", tolerance="foo")
|
||||
|
||||
with pytest.raises(ValueError, match="tolerance size must match"):
|
||||
idx.get_loc(
|
||||
idx[1],
|
||||
method="nearest",
|
||||
tolerance=[
|
||||
Timedelta(0).to_timedelta64(),
|
||||
Timedelta(0).to_timedelta64(),
|
||||
],
|
||||
)
|
||||
|
||||
for method, loc in [("pad", 1), ("backfill", 2), ("nearest", 1)]:
|
||||
assert idx.get_loc("1 day 1 hour", method) == loc
|
||||
|
||||
# GH 16909
|
||||
assert idx.get_loc(idx[1].to_timedelta64()) == 1
|
||||
|
||||
# GH 16896
|
||||
assert idx.get_loc("0 days") == 0
|
||||
|
||||
def test_get_loc_nat(self):
|
||||
tidx = TimedeltaIndex(["1 days 01:00:00", "NaT", "2 days 01:00:00"])
|
||||
|
||||
assert tidx.get_loc(pd.NaT) == 1
|
||||
assert tidx.get_loc(None) == 1
|
||||
assert tidx.get_loc(float("nan")) == 1
|
||||
assert tidx.get_loc(np.nan) == 1
|
||||
|
||||
def test_get_indexer(self):
|
||||
idx = pd.to_timedelta(["0 days", "1 days", "2 days"])
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
|
||||
target = pd.to_timedelta(["-1 hour", "12 hours", "1 day 1 hour"])
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "pad"), np.array([-1, 0, 1], dtype=np.intp)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "backfill"), np.array([0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "nearest"), np.array([0, 1, 1], dtype=np.intp)
|
||||
)
|
||||
|
||||
res = idx.get_indexer(target, "nearest", tolerance=Timedelta("1 hour"))
|
||||
tm.assert_numpy_array_equal(res, np.array([0, -1, 1], dtype=np.intp))
|
@@ -0,0 +1,303 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas.core.dtypes.generic import ABCDateOffset
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Series, TimedeltaIndex, timedelta_range
|
||||
from pandas.tests.test_base import Ops
|
||||
import pandas.util.testing as tm
|
||||
|
||||
from pandas.tseries.offsets import Day, Hour
|
||||
|
||||
|
||||
class TestTimedeltaIndexOps(Ops):
|
||||
def setup_method(self, method):
|
||||
super().setup_method(method)
|
||||
mask = lambda x: isinstance(x, TimedeltaIndex)
|
||||
self.is_valid_objs = [o for o in self.objs if mask(o)]
|
||||
self.not_valid_objs = []
|
||||
|
||||
def test_ops_properties(self):
|
||||
f = lambda x: isinstance(x, TimedeltaIndex)
|
||||
self.check_ops_properties(TimedeltaIndex._field_ops, f)
|
||||
self.check_ops_properties(TimedeltaIndex._object_ops, f)
|
||||
|
||||
def test_value_counts_unique(self):
|
||||
# GH 7735
|
||||
|
||||
idx = timedelta_range("1 days 09:00:00", freq="H", periods=10)
|
||||
# create repeated values, 'n'th element is repeated by n+1 times
|
||||
idx = TimedeltaIndex(np.repeat(idx.values, range(1, len(idx) + 1)))
|
||||
|
||||
exp_idx = timedelta_range("1 days 18:00:00", freq="-1H", periods=10)
|
||||
expected = Series(range(10, 0, -1), index=exp_idx, dtype="int64")
|
||||
|
||||
for obj in [idx, Series(idx)]:
|
||||
tm.assert_series_equal(obj.value_counts(), expected)
|
||||
|
||||
expected = timedelta_range("1 days 09:00:00", freq="H", periods=10)
|
||||
tm.assert_index_equal(idx.unique(), expected)
|
||||
|
||||
idx = TimedeltaIndex(
|
||||
[
|
||||
"1 days 09:00:00",
|
||||
"1 days 09:00:00",
|
||||
"1 days 09:00:00",
|
||||
"1 days 08:00:00",
|
||||
"1 days 08:00:00",
|
||||
pd.NaT,
|
||||
]
|
||||
)
|
||||
|
||||
exp_idx = TimedeltaIndex(["1 days 09:00:00", "1 days 08:00:00"])
|
||||
expected = Series([3, 2], index=exp_idx)
|
||||
|
||||
for obj in [idx, Series(idx)]:
|
||||
tm.assert_series_equal(obj.value_counts(), expected)
|
||||
|
||||
exp_idx = TimedeltaIndex(["1 days 09:00:00", "1 days 08:00:00", pd.NaT])
|
||||
expected = Series([3, 2, 1], index=exp_idx)
|
||||
|
||||
for obj in [idx, Series(idx)]:
|
||||
tm.assert_series_equal(obj.value_counts(dropna=False), expected)
|
||||
|
||||
tm.assert_index_equal(idx.unique(), exp_idx)
|
||||
|
||||
def test_nonunique_contains(self):
|
||||
# GH 9512
|
||||
for idx in map(
|
||||
TimedeltaIndex,
|
||||
(
|
||||
[0, 1, 0],
|
||||
[0, 0, -1],
|
||||
[0, -1, -1],
|
||||
["00:01:00", "00:01:00", "00:02:00"],
|
||||
["00:01:00", "00:01:00", "00:00:01"],
|
||||
),
|
||||
):
|
||||
assert idx[0] in idx
|
||||
|
||||
def test_unknown_attribute(self):
|
||||
# see gh-9680
|
||||
tdi = pd.timedelta_range(start=0, periods=10, freq="1s")
|
||||
ts = pd.Series(np.random.normal(size=10), index=tdi)
|
||||
assert "foo" not in ts.__dict__.keys()
|
||||
msg = "'Series' object has no attribute 'foo'"
|
||||
with pytest.raises(AttributeError, match=msg):
|
||||
ts.foo
|
||||
|
||||
def test_order(self):
|
||||
# GH 10295
|
||||
idx1 = TimedeltaIndex(["1 day", "2 day", "3 day"], freq="D", name="idx")
|
||||
idx2 = TimedeltaIndex(["1 hour", "2 hour", "3 hour"], freq="H", name="idx")
|
||||
|
||||
for idx in [idx1, idx2]:
|
||||
ordered = idx.sort_values()
|
||||
tm.assert_index_equal(ordered, idx)
|
||||
assert ordered.freq == idx.freq
|
||||
|
||||
ordered = idx.sort_values(ascending=False)
|
||||
expected = idx[::-1]
|
||||
tm.assert_index_equal(ordered, expected)
|
||||
assert ordered.freq == expected.freq
|
||||
assert ordered.freq.n == -1
|
||||
|
||||
ordered, indexer = idx.sort_values(return_indexer=True)
|
||||
tm.assert_index_equal(ordered, idx)
|
||||
tm.assert_numpy_array_equal(indexer, np.array([0, 1, 2]), check_dtype=False)
|
||||
assert ordered.freq == idx.freq
|
||||
|
||||
ordered, indexer = idx.sort_values(return_indexer=True, ascending=False)
|
||||
tm.assert_index_equal(ordered, idx[::-1])
|
||||
assert ordered.freq == expected.freq
|
||||
assert ordered.freq.n == -1
|
||||
|
||||
idx1 = TimedeltaIndex(
|
||||
["1 hour", "3 hour", "5 hour", "2 hour ", "1 hour"], name="idx1"
|
||||
)
|
||||
exp1 = TimedeltaIndex(
|
||||
["1 hour", "1 hour", "2 hour", "3 hour", "5 hour"], name="idx1"
|
||||
)
|
||||
|
||||
idx2 = TimedeltaIndex(
|
||||
["1 day", "3 day", "5 day", "2 day", "1 day"], name="idx2"
|
||||
)
|
||||
|
||||
# TODO(wesm): unused?
|
||||
# exp2 = TimedeltaIndex(['1 day', '1 day', '2 day',
|
||||
# '3 day', '5 day'], name='idx2')
|
||||
|
||||
# idx3 = TimedeltaIndex([pd.NaT, '3 minute', '5 minute',
|
||||
# '2 minute', pd.NaT], name='idx3')
|
||||
# exp3 = TimedeltaIndex([pd.NaT, pd.NaT, '2 minute', '3 minute',
|
||||
# '5 minute'], name='idx3')
|
||||
|
||||
for idx, expected in [(idx1, exp1), (idx1, exp1), (idx1, exp1)]:
|
||||
ordered = idx.sort_values()
|
||||
tm.assert_index_equal(ordered, expected)
|
||||
assert ordered.freq is None
|
||||
|
||||
ordered = idx.sort_values(ascending=False)
|
||||
tm.assert_index_equal(ordered, expected[::-1])
|
||||
assert ordered.freq is None
|
||||
|
||||
ordered, indexer = idx.sort_values(return_indexer=True)
|
||||
tm.assert_index_equal(ordered, expected)
|
||||
|
||||
exp = np.array([0, 4, 3, 1, 2])
|
||||
tm.assert_numpy_array_equal(indexer, exp, check_dtype=False)
|
||||
assert ordered.freq is None
|
||||
|
||||
ordered, indexer = idx.sort_values(return_indexer=True, ascending=False)
|
||||
tm.assert_index_equal(ordered, expected[::-1])
|
||||
|
||||
exp = np.array([2, 1, 3, 4, 0])
|
||||
tm.assert_numpy_array_equal(indexer, exp, check_dtype=False)
|
||||
assert ordered.freq is None
|
||||
|
||||
def test_drop_duplicates_metadata(self):
|
||||
# GH 10115
|
||||
idx = pd.timedelta_range("1 day", "31 day", freq="D", name="idx")
|
||||
result = idx.drop_duplicates()
|
||||
tm.assert_index_equal(idx, result)
|
||||
assert idx.freq == result.freq
|
||||
|
||||
idx_dup = idx.append(idx)
|
||||
assert idx_dup.freq is None # freq is reset
|
||||
result = idx_dup.drop_duplicates()
|
||||
tm.assert_index_equal(idx, result)
|
||||
assert result.freq is None
|
||||
|
||||
def test_drop_duplicates(self):
|
||||
# to check Index/Series compat
|
||||
base = pd.timedelta_range("1 day", "31 day", freq="D", name="idx")
|
||||
idx = base.append(base[:5])
|
||||
|
||||
res = idx.drop_duplicates()
|
||||
tm.assert_index_equal(res, base)
|
||||
res = Series(idx).drop_duplicates()
|
||||
tm.assert_series_equal(res, Series(base))
|
||||
|
||||
res = idx.drop_duplicates(keep="last")
|
||||
exp = base[5:].append(base[:5])
|
||||
tm.assert_index_equal(res, exp)
|
||||
res = Series(idx).drop_duplicates(keep="last")
|
||||
tm.assert_series_equal(res, Series(exp, index=np.arange(5, 36)))
|
||||
|
||||
res = idx.drop_duplicates(keep=False)
|
||||
tm.assert_index_equal(res, base[5:])
|
||||
res = Series(idx).drop_duplicates(keep=False)
|
||||
tm.assert_series_equal(res, Series(base[5:], index=np.arange(5, 31)))
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq", ["D", "3D", "-3D", "H", "2H", "-2H", "T", "2T", "S", "-3S"]
|
||||
)
|
||||
def test_infer_freq(self, freq):
|
||||
# GH#11018
|
||||
idx = pd.timedelta_range("1", freq=freq, periods=10)
|
||||
result = pd.TimedeltaIndex(idx.asi8, freq="infer")
|
||||
tm.assert_index_equal(idx, result)
|
||||
assert result.freq == freq
|
||||
|
||||
def test_shift(self):
|
||||
pass # handled in test_arithmetic.py
|
||||
|
||||
def test_repeat(self):
|
||||
index = pd.timedelta_range("1 days", periods=2, freq="D")
|
||||
exp = pd.TimedeltaIndex(["1 days", "1 days", "2 days", "2 days"])
|
||||
for res in [index.repeat(2), np.repeat(index, 2)]:
|
||||
tm.assert_index_equal(res, exp)
|
||||
assert res.freq is None
|
||||
|
||||
index = TimedeltaIndex(["1 days", "NaT", "3 days"])
|
||||
exp = TimedeltaIndex(
|
||||
[
|
||||
"1 days",
|
||||
"1 days",
|
||||
"1 days",
|
||||
"NaT",
|
||||
"NaT",
|
||||
"NaT",
|
||||
"3 days",
|
||||
"3 days",
|
||||
"3 days",
|
||||
]
|
||||
)
|
||||
for res in [index.repeat(3), np.repeat(index, 3)]:
|
||||
tm.assert_index_equal(res, exp)
|
||||
assert res.freq is None
|
||||
|
||||
def test_nat(self):
|
||||
assert pd.TimedeltaIndex._na_value is pd.NaT
|
||||
assert pd.TimedeltaIndex([])._na_value is pd.NaT
|
||||
|
||||
idx = pd.TimedeltaIndex(["1 days", "2 days"])
|
||||
assert idx._can_hold_na
|
||||
|
||||
tm.assert_numpy_array_equal(idx._isnan, np.array([False, False]))
|
||||
assert idx.hasnans is False
|
||||
tm.assert_numpy_array_equal(idx._nan_idxs, np.array([], dtype=np.intp))
|
||||
|
||||
idx = pd.TimedeltaIndex(["1 days", "NaT"])
|
||||
assert idx._can_hold_na
|
||||
|
||||
tm.assert_numpy_array_equal(idx._isnan, np.array([False, True]))
|
||||
assert idx.hasnans is True
|
||||
tm.assert_numpy_array_equal(idx._nan_idxs, np.array([1], dtype=np.intp))
|
||||
|
||||
def test_equals(self):
|
||||
# GH 13107
|
||||
idx = pd.TimedeltaIndex(["1 days", "2 days", "NaT"])
|
||||
assert idx.equals(idx)
|
||||
assert idx.equals(idx.copy())
|
||||
assert idx.equals(idx.astype(object))
|
||||
assert idx.astype(object).equals(idx)
|
||||
assert idx.astype(object).equals(idx.astype(object))
|
||||
assert not idx.equals(list(idx))
|
||||
assert not idx.equals(pd.Series(idx))
|
||||
|
||||
idx2 = pd.TimedeltaIndex(["2 days", "1 days", "NaT"])
|
||||
assert not idx.equals(idx2)
|
||||
assert not idx.equals(idx2.copy())
|
||||
assert not idx.equals(idx2.astype(object))
|
||||
assert not idx.astype(object).equals(idx2)
|
||||
assert not idx.astype(object).equals(idx2.astype(object))
|
||||
assert not idx.equals(list(idx2))
|
||||
assert not idx.equals(pd.Series(idx2))
|
||||
|
||||
@pytest.mark.parametrize("values", [["0 days", "2 days", "4 days"], []])
|
||||
@pytest.mark.parametrize("freq", ["2D", Day(2), "48H", Hour(48)])
|
||||
def test_freq_setter(self, values, freq):
|
||||
# GH 20678
|
||||
idx = TimedeltaIndex(values)
|
||||
|
||||
# can set to an offset, converting from string if necessary
|
||||
idx.freq = freq
|
||||
assert idx.freq == freq
|
||||
assert isinstance(idx.freq, ABCDateOffset)
|
||||
|
||||
# can reset to None
|
||||
idx.freq = None
|
||||
assert idx.freq is None
|
||||
|
||||
def test_freq_setter_errors(self):
|
||||
# GH 20678
|
||||
idx = TimedeltaIndex(["0 days", "2 days", "4 days"])
|
||||
|
||||
# setting with an incompatible freq
|
||||
msg = (
|
||||
"Inferred frequency 2D from passed values does not conform to "
|
||||
"passed frequency 5D"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.freq = "5D"
|
||||
|
||||
# setting with a non-fixed frequency
|
||||
msg = r"<2 \* BusinessDays> is a non-fixed frequency"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.freq = "2B"
|
||||
|
||||
# setting with non-freq string
|
||||
with pytest.raises(ValueError, match="Invalid frequency"):
|
||||
idx.freq = "foo"
|
@@ -0,0 +1,90 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Series, Timedelta, timedelta_range
|
||||
from pandas.util.testing import assert_series_equal
|
||||
|
||||
|
||||
class TestSlicing:
|
||||
def test_slice_keeps_name(self):
|
||||
# GH4226
|
||||
dr = pd.timedelta_range("1d", "5d", freq="H", name="timebucket")
|
||||
assert dr[1:].name == dr.name
|
||||
|
||||
def test_partial_slice(self):
|
||||
rng = timedelta_range("1 day 10:11:12", freq="h", periods=500)
|
||||
s = Series(np.arange(len(rng)), index=rng)
|
||||
|
||||
result = s["5 day":"6 day"]
|
||||
expected = s.iloc[86:134]
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = s["5 day":]
|
||||
expected = s.iloc[86:]
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = s[:"6 day"]
|
||||
expected = s.iloc[:134]
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = s["6 days, 23:11:12"]
|
||||
assert result == s.iloc[133]
|
||||
|
||||
msg = r"^Timedelta\('50 days 00:00:00'\)$"
|
||||
with pytest.raises(KeyError, match=msg):
|
||||
s["50 days"]
|
||||
|
||||
def test_partial_slice_high_reso(self):
|
||||
|
||||
# higher reso
|
||||
rng = timedelta_range("1 day 10:11:12", freq="us", periods=2000)
|
||||
s = Series(np.arange(len(rng)), index=rng)
|
||||
|
||||
result = s["1 day 10:11:12":]
|
||||
expected = s.iloc[0:]
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = s["1 day 10:11:12.001":]
|
||||
expected = s.iloc[1000:]
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = s["1 days, 10:11:12.001001"]
|
||||
assert result == s.iloc[1001]
|
||||
|
||||
def test_slice_with_negative_step(self):
|
||||
ts = Series(np.arange(20), timedelta_range("0", periods=20, freq="H"))
|
||||
SLC = pd.IndexSlice
|
||||
|
||||
def assert_slices_equivalent(l_slc, i_slc):
|
||||
assert_series_equal(ts[l_slc], ts.iloc[i_slc])
|
||||
assert_series_equal(ts.loc[l_slc], ts.iloc[i_slc])
|
||||
assert_series_equal(ts.loc[l_slc], ts.iloc[i_slc])
|
||||
|
||||
assert_slices_equivalent(SLC[Timedelta(hours=7) :: -1], SLC[7::-1])
|
||||
assert_slices_equivalent(SLC["7 hours"::-1], SLC[7::-1])
|
||||
|
||||
assert_slices_equivalent(SLC[: Timedelta(hours=7) : -1], SLC[:6:-1])
|
||||
assert_slices_equivalent(SLC[:"7 hours":-1], SLC[:6:-1])
|
||||
|
||||
assert_slices_equivalent(SLC["15 hours":"7 hours":-1], SLC[15:6:-1])
|
||||
assert_slices_equivalent(
|
||||
SLC[Timedelta(hours=15) : Timedelta(hours=7) : -1], SLC[15:6:-1]
|
||||
)
|
||||
assert_slices_equivalent(
|
||||
SLC["15 hours" : Timedelta(hours=7) : -1], SLC[15:6:-1]
|
||||
)
|
||||
assert_slices_equivalent(
|
||||
SLC[Timedelta(hours=15) : "7 hours" : -1], SLC[15:6:-1]
|
||||
)
|
||||
|
||||
assert_slices_equivalent(SLC["7 hours":"15 hours":-1], SLC[:0])
|
||||
|
||||
def test_slice_with_zero_step_raises(self):
|
||||
ts = Series(np.arange(20), timedelta_range("0", periods=20, freq="H"))
|
||||
with pytest.raises(ValueError, match="slice step cannot be zero"):
|
||||
ts[::0]
|
||||
with pytest.raises(ValueError, match="slice step cannot be zero"):
|
||||
ts.loc[::0]
|
||||
with pytest.raises(ValueError, match="slice step cannot be zero"):
|
||||
ts.loc[::0]
|
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
Tests for TimedeltaIndex methods behaving like their Timedelta counterparts
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Index, Series, Timedelta, TimedeltaIndex, timedelta_range
|
||||
import pandas.util.testing as tm
|
||||
|
||||
|
||||
class TestVectorizedTimedelta:
|
||||
def test_tdi_total_seconds(self):
|
||||
# GH#10939
|
||||
# test index
|
||||
rng = timedelta_range("1 days, 10:11:12.100123456", periods=2, freq="s")
|
||||
expt = [
|
||||
1 * 86400 + 10 * 3600 + 11 * 60 + 12 + 100123456.0 / 1e9,
|
||||
1 * 86400 + 10 * 3600 + 11 * 60 + 13 + 100123456.0 / 1e9,
|
||||
]
|
||||
tm.assert_almost_equal(rng.total_seconds(), Index(expt))
|
||||
|
||||
# test Series
|
||||
ser = Series(rng)
|
||||
s_expt = Series(expt, index=[0, 1])
|
||||
tm.assert_series_equal(ser.dt.total_seconds(), s_expt)
|
||||
|
||||
# with nat
|
||||
ser[1] = np.nan
|
||||
s_expt = Series(
|
||||
[1 * 86400 + 10 * 3600 + 11 * 60 + 12 + 100123456.0 / 1e9, np.nan],
|
||||
index=[0, 1],
|
||||
)
|
||||
tm.assert_series_equal(ser.dt.total_seconds(), s_expt)
|
||||
|
||||
# with both nat
|
||||
ser = Series([np.nan, np.nan], dtype="timedelta64[ns]")
|
||||
tm.assert_series_equal(
|
||||
ser.dt.total_seconds(), Series([np.nan, np.nan], index=[0, 1])
|
||||
)
|
||||
|
||||
def test_tdi_round(self):
|
||||
td = pd.timedelta_range(start="16801 days", periods=5, freq="30Min")
|
||||
elt = td[1]
|
||||
|
||||
expected_rng = TimedeltaIndex(
|
||||
[
|
||||
Timedelta("16801 days 00:00:00"),
|
||||
Timedelta("16801 days 00:00:00"),
|
||||
Timedelta("16801 days 01:00:00"),
|
||||
Timedelta("16801 days 02:00:00"),
|
||||
Timedelta("16801 days 02:00:00"),
|
||||
]
|
||||
)
|
||||
expected_elt = expected_rng[1]
|
||||
|
||||
tm.assert_index_equal(td.round(freq="H"), expected_rng)
|
||||
assert elt.round(freq="H") == expected_elt
|
||||
|
||||
msg = pd._libs.tslibs.frequencies.INVALID_FREQ_ERR_MSG
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
td.round(freq="foo")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
elt.round(freq="foo")
|
||||
|
||||
msg = "<MonthEnd> is a non-fixed frequency"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
td.round(freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
elt.round(freq="M")
|
@@ -0,0 +1,181 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Int64Index, TimedeltaIndex, timedelta_range
|
||||
import pandas.util.testing as tm
|
||||
|
||||
from pandas.tseries.offsets import Hour
|
||||
|
||||
|
||||
class TestTimedeltaIndex:
|
||||
def test_union(self):
|
||||
|
||||
i1 = timedelta_range("1day", periods=5)
|
||||
i2 = timedelta_range("3day", periods=5)
|
||||
result = i1.union(i2)
|
||||
expected = timedelta_range("1day", periods=7)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
i1 = Int64Index(np.arange(0, 20, 2))
|
||||
i2 = timedelta_range(start="1 day", periods=10, freq="D")
|
||||
i1.union(i2) # Works
|
||||
i2.union(i1) # Fails with "AttributeError: can't set attribute"
|
||||
|
||||
def test_union_coverage(self):
|
||||
|
||||
idx = TimedeltaIndex(["3d", "1d", "2d"])
|
||||
ordered = TimedeltaIndex(idx.sort_values(), freq="infer")
|
||||
result = ordered.union(idx)
|
||||
tm.assert_index_equal(result, ordered)
|
||||
|
||||
result = ordered[:0].union(ordered)
|
||||
tm.assert_index_equal(result, ordered)
|
||||
assert result.freq == ordered.freq
|
||||
|
||||
def test_union_bug_1730(self):
|
||||
|
||||
rng_a = timedelta_range("1 day", periods=4, freq="3H")
|
||||
rng_b = timedelta_range("1 day", periods=4, freq="4H")
|
||||
|
||||
result = rng_a.union(rng_b)
|
||||
exp = TimedeltaIndex(sorted(set(list(rng_a)) | set(list(rng_b))))
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_union_bug_1745(self):
|
||||
|
||||
left = TimedeltaIndex(["1 day 15:19:49.695000"])
|
||||
right = TimedeltaIndex(
|
||||
["2 day 13:04:21.322000", "1 day 15:27:24.873000", "1 day 15:31:05.350000"]
|
||||
)
|
||||
|
||||
result = left.union(right)
|
||||
exp = TimedeltaIndex(sorted(set(list(left)) | set(list(right))))
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_union_bug_4564(self):
|
||||
|
||||
left = timedelta_range("1 day", "30d")
|
||||
right = left + pd.offsets.Minute(15)
|
||||
|
||||
result = left.union(right)
|
||||
exp = TimedeltaIndex(sorted(set(list(left)) | set(list(right))))
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_intersection_bug_1708(self):
|
||||
index_1 = timedelta_range("1 day", periods=4, freq="h")
|
||||
index_2 = index_1 + pd.offsets.Hour(5)
|
||||
|
||||
result = index_1 & index_2
|
||||
assert len(result) == 0
|
||||
|
||||
index_1 = timedelta_range("1 day", periods=4, freq="h")
|
||||
index_2 = index_1 + pd.offsets.Hour(1)
|
||||
|
||||
result = index_1 & index_2
|
||||
expected = timedelta_range("1 day 01:00:00", periods=3, freq="h")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_intersection_equal(self, sort):
|
||||
# GH 24471 Test intersection outcome given the sort keyword
|
||||
# for equal indicies intersection should return the original index
|
||||
first = timedelta_range("1 day", periods=4, freq="h")
|
||||
second = timedelta_range("1 day", periods=4, freq="h")
|
||||
intersect = first.intersection(second, sort=sort)
|
||||
if sort is None:
|
||||
tm.assert_index_equal(intersect, second.sort_values())
|
||||
assert tm.equalContents(intersect, second)
|
||||
|
||||
# Corner cases
|
||||
inter = first.intersection(first, sort=sort)
|
||||
assert inter is first
|
||||
|
||||
@pytest.mark.parametrize("period_1, period_2", [(0, 4), (4, 0)])
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_intersection_zero_length(self, period_1, period_2, sort):
|
||||
# GH 24471 test for non overlap the intersection should be zero length
|
||||
index_1 = timedelta_range("1 day", periods=period_1, freq="h")
|
||||
index_2 = timedelta_range("1 day", periods=period_2, freq="h")
|
||||
expected = timedelta_range("1 day", periods=0, freq="h")
|
||||
result = index_1.intersection(index_2, sort=sort)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_zero_length_input_index(self, sort):
|
||||
# GH 24966 test for 0-len intersections are copied
|
||||
index_1 = timedelta_range("1 day", periods=0, freq="h")
|
||||
index_2 = timedelta_range("1 day", periods=3, freq="h")
|
||||
result = index_1.intersection(index_2, sort=sort)
|
||||
assert index_1 is not result
|
||||
assert index_2 is not result
|
||||
tm.assert_copy(result, index_1)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"rng, expected",
|
||||
# if target has the same name, it is preserved
|
||||
[
|
||||
(
|
||||
timedelta_range("1 day", periods=5, freq="h", name="idx"),
|
||||
timedelta_range("1 day", periods=4, freq="h", name="idx"),
|
||||
),
|
||||
# if target name is different, it will be reset
|
||||
(
|
||||
timedelta_range("1 day", periods=5, freq="h", name="other"),
|
||||
timedelta_range("1 day", periods=4, freq="h", name=None),
|
||||
),
|
||||
# if no overlap exists return empty index
|
||||
(
|
||||
timedelta_range("1 day", periods=10, freq="h", name="idx")[5:],
|
||||
TimedeltaIndex([], name="idx"),
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_intersection(self, rng, expected, sort):
|
||||
# GH 4690 (with tz)
|
||||
base = timedelta_range("1 day", periods=4, freq="h", name="idx")
|
||||
result = base.intersection(rng, sort=sort)
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert result.freq == expected.freq
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"rng, expected",
|
||||
# part intersection works
|
||||
[
|
||||
(
|
||||
TimedeltaIndex(["5 hour", "2 hour", "4 hour", "9 hour"], name="idx"),
|
||||
TimedeltaIndex(["2 hour", "4 hour"], name="idx"),
|
||||
),
|
||||
# reordered part intersection
|
||||
(
|
||||
TimedeltaIndex(["2 hour", "5 hour", "5 hour", "1 hour"], name="other"),
|
||||
TimedeltaIndex(["1 hour", "2 hour"], name=None),
|
||||
),
|
||||
# reveresed index
|
||||
(
|
||||
TimedeltaIndex(["1 hour", "2 hour", "4 hour", "3 hour"], name="idx")[
|
||||
::-1
|
||||
],
|
||||
TimedeltaIndex(["1 hour", "2 hour", "4 hour", "3 hour"], name="idx"),
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_intersection_non_monotonic(self, rng, expected, sort):
|
||||
# 24471 non-monotonic
|
||||
base = TimedeltaIndex(["1 hour", "2 hour", "4 hour", "3 hour"], name="idx")
|
||||
result = base.intersection(rng, sort=sort)
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
|
||||
# if reveresed order, frequency is still the same
|
||||
if all(base == rng[::-1]) and sort is None:
|
||||
assert isinstance(result.freq, Hour)
|
||||
else:
|
||||
assert result.freq is None
|
@@ -0,0 +1,356 @@
|
||||
from datetime import timedelta
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
DataFrame,
|
||||
Index,
|
||||
Int64Index,
|
||||
Series,
|
||||
Timedelta,
|
||||
TimedeltaIndex,
|
||||
date_range,
|
||||
timedelta_range,
|
||||
)
|
||||
import pandas.util.testing as tm
|
||||
from pandas.util.testing import (
|
||||
assert_almost_equal,
|
||||
assert_index_equal,
|
||||
assert_series_equal,
|
||||
)
|
||||
|
||||
from ..datetimelike import DatetimeLike
|
||||
|
||||
randn = np.random.randn
|
||||
|
||||
|
||||
class TestTimedeltaIndex(DatetimeLike):
|
||||
_holder = TimedeltaIndex
|
||||
|
||||
def setup_method(self, method):
|
||||
self.indices = dict(index=tm.makeTimedeltaIndex(10))
|
||||
self.setup_indices()
|
||||
|
||||
def create_index(self):
|
||||
return pd.to_timedelta(range(5), unit="d") + pd.offsets.Hour(1)
|
||||
|
||||
def test_numeric_compat(self):
|
||||
# Dummy method to override super's version; this test is now done
|
||||
# in test_arithmetic.py
|
||||
pass
|
||||
|
||||
def test_shift(self):
|
||||
pass # this is handled in test_arithmetic.py
|
||||
|
||||
def test_pickle_compat_construction(self):
|
||||
pass
|
||||
|
||||
def test_fillna_timedelta(self):
|
||||
# GH 11343
|
||||
idx = pd.TimedeltaIndex(["1 day", pd.NaT, "3 day"])
|
||||
|
||||
exp = pd.TimedeltaIndex(["1 day", "2 day", "3 day"])
|
||||
tm.assert_index_equal(idx.fillna(pd.Timedelta("2 day")), exp)
|
||||
|
||||
exp = pd.TimedeltaIndex(["1 day", "3 hour", "3 day"])
|
||||
idx.fillna(pd.Timedelta("3 hour"))
|
||||
|
||||
exp = pd.Index(
|
||||
[pd.Timedelta("1 day"), "x", pd.Timedelta("3 day")], dtype=object
|
||||
)
|
||||
tm.assert_index_equal(idx.fillna("x"), exp)
|
||||
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_difference_freq(self, sort):
|
||||
# GH14323: Difference of TimedeltaIndex should not preserve frequency
|
||||
|
||||
index = timedelta_range("0 days", "5 days", freq="D")
|
||||
|
||||
other = timedelta_range("1 days", "4 days", freq="D")
|
||||
expected = TimedeltaIndex(["0 days", "5 days"], freq=None)
|
||||
idx_diff = index.difference(other, sort)
|
||||
tm.assert_index_equal(idx_diff, expected)
|
||||
tm.assert_attr_equal("freq", idx_diff, expected)
|
||||
|
||||
other = timedelta_range("2 days", "5 days", freq="D")
|
||||
idx_diff = index.difference(other, sort)
|
||||
expected = TimedeltaIndex(["0 days", "1 days"], freq=None)
|
||||
tm.assert_index_equal(idx_diff, expected)
|
||||
tm.assert_attr_equal("freq", idx_diff, expected)
|
||||
|
||||
@pytest.mark.parametrize("sort", [None, False])
|
||||
def test_difference_sort(self, sort):
|
||||
|
||||
index = pd.TimedeltaIndex(
|
||||
["5 days", "3 days", "2 days", "4 days", "1 days", "0 days"]
|
||||
)
|
||||
|
||||
other = timedelta_range("1 days", "4 days", freq="D")
|
||||
idx_diff = index.difference(other, sort)
|
||||
|
||||
expected = TimedeltaIndex(["5 days", "0 days"], freq=None)
|
||||
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
|
||||
tm.assert_index_equal(idx_diff, expected)
|
||||
tm.assert_attr_equal("freq", idx_diff, expected)
|
||||
|
||||
other = timedelta_range("2 days", "5 days", freq="D")
|
||||
idx_diff = index.difference(other, sort)
|
||||
expected = TimedeltaIndex(["1 days", "0 days"], freq=None)
|
||||
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
|
||||
tm.assert_index_equal(idx_diff, expected)
|
||||
tm.assert_attr_equal("freq", idx_diff, expected)
|
||||
|
||||
def test_isin(self):
|
||||
|
||||
index = tm.makeTimedeltaIndex(4)
|
||||
result = index.isin(index)
|
||||
assert result.all()
|
||||
|
||||
result = index.isin(list(index))
|
||||
assert result.all()
|
||||
|
||||
assert_almost_equal(
|
||||
index.isin([index[2], 5]), np.array([False, False, True, False])
|
||||
)
|
||||
|
||||
def test_factorize(self):
|
||||
idx1 = TimedeltaIndex(["1 day", "1 day", "2 day", "2 day", "3 day", "3 day"])
|
||||
|
||||
exp_arr = np.array([0, 0, 1, 1, 2, 2], dtype=np.intp)
|
||||
exp_idx = TimedeltaIndex(["1 day", "2 day", "3 day"])
|
||||
|
||||
arr, idx = idx1.factorize()
|
||||
tm.assert_numpy_array_equal(arr, exp_arr)
|
||||
tm.assert_index_equal(idx, exp_idx)
|
||||
|
||||
arr, idx = idx1.factorize(sort=True)
|
||||
tm.assert_numpy_array_equal(arr, exp_arr)
|
||||
tm.assert_index_equal(idx, exp_idx)
|
||||
|
||||
# freq must be preserved
|
||||
idx3 = timedelta_range("1 day", periods=4, freq="s")
|
||||
exp_arr = np.array([0, 1, 2, 3], dtype=np.intp)
|
||||
arr, idx = idx3.factorize()
|
||||
tm.assert_numpy_array_equal(arr, exp_arr)
|
||||
tm.assert_index_equal(idx, idx3)
|
||||
|
||||
def test_join_self(self, join_type):
|
||||
index = timedelta_range("1 day", periods=10)
|
||||
joined = index.join(index, how=join_type)
|
||||
tm.assert_index_equal(index, joined)
|
||||
|
||||
def test_does_not_convert_mixed_integer(self):
|
||||
df = tm.makeCustomDataframe(
|
||||
10,
|
||||
10,
|
||||
data_gen_f=lambda *args, **kwargs: randn(),
|
||||
r_idx_type="i",
|
||||
c_idx_type="td",
|
||||
)
|
||||
str(df)
|
||||
|
||||
cols = df.columns.join(df.index, how="outer")
|
||||
joined = cols.join(df.columns)
|
||||
assert cols.dtype == np.dtype("O")
|
||||
assert cols.dtype == joined.dtype
|
||||
tm.assert_index_equal(cols, joined)
|
||||
|
||||
def test_sort_values(self):
|
||||
|
||||
idx = TimedeltaIndex(["4d", "1d", "2d"])
|
||||
|
||||
ordered = idx.sort_values()
|
||||
assert ordered.is_monotonic
|
||||
|
||||
ordered = idx.sort_values(ascending=False)
|
||||
assert ordered[::-1].is_monotonic
|
||||
|
||||
ordered, dexer = idx.sort_values(return_indexer=True)
|
||||
assert ordered.is_monotonic
|
||||
|
||||
tm.assert_numpy_array_equal(dexer, np.array([1, 2, 0]), check_dtype=False)
|
||||
|
||||
ordered, dexer = idx.sort_values(return_indexer=True, ascending=False)
|
||||
assert ordered[::-1].is_monotonic
|
||||
|
||||
tm.assert_numpy_array_equal(dexer, np.array([0, 2, 1]), check_dtype=False)
|
||||
|
||||
def test_get_duplicates(self):
|
||||
idx = TimedeltaIndex(["1 day", "2 day", "2 day", "3 day", "3day", "4day"])
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
# Deprecated - see GH20239
|
||||
result = idx.get_duplicates()
|
||||
|
||||
ex = TimedeltaIndex(["2 day", "3day"])
|
||||
tm.assert_index_equal(result, ex)
|
||||
|
||||
def test_argmin_argmax(self):
|
||||
idx = TimedeltaIndex(["1 day 00:00:05", "1 day 00:00:01", "1 day 00:00:02"])
|
||||
assert idx.argmin() == 1
|
||||
assert idx.argmax() == 0
|
||||
|
||||
def test_misc_coverage(self):
|
||||
|
||||
rng = timedelta_range("1 day", periods=5)
|
||||
result = rng.groupby(rng.days)
|
||||
assert isinstance(list(result.values())[0][0], Timedelta)
|
||||
|
||||
idx = TimedeltaIndex(["3d", "1d", "2d"])
|
||||
assert not idx.equals(list(idx))
|
||||
|
||||
non_td = Index(list("abc"))
|
||||
assert not idx.equals(list(non_td))
|
||||
|
||||
def test_map(self):
|
||||
# test_map_dictlike generally tests
|
||||
|
||||
rng = timedelta_range("1 day", periods=10)
|
||||
|
||||
f = lambda x: x.days
|
||||
result = rng.map(f)
|
||||
exp = Int64Index([f(x) for x in rng])
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_pass_TimedeltaIndex_to_index(self):
|
||||
|
||||
rng = timedelta_range("1 days", "10 days")
|
||||
idx = Index(rng, dtype=object)
|
||||
|
||||
expected = Index(rng.to_pytimedelta(), dtype=object)
|
||||
|
||||
tm.assert_numpy_array_equal(idx.values, expected.values)
|
||||
|
||||
def test_pickle(self):
|
||||
|
||||
rng = timedelta_range("1 days", periods=10)
|
||||
rng_p = tm.round_trip_pickle(rng)
|
||||
tm.assert_index_equal(rng, rng_p)
|
||||
|
||||
def test_hash_error(self):
|
||||
index = timedelta_range("1 days", periods=10)
|
||||
with pytest.raises(
|
||||
TypeError, match=("unhashable type: {0.__name__!r}".format(type(index)))
|
||||
):
|
||||
hash(index)
|
||||
|
||||
def test_append_join_nondatetimeindex(self):
|
||||
rng = timedelta_range("1 days", periods=10)
|
||||
idx = Index(["a", "b", "c", "d"])
|
||||
|
||||
result = rng.append(idx)
|
||||
assert isinstance(result[0], Timedelta)
|
||||
|
||||
# it works
|
||||
rng.join(idx, how="outer")
|
||||
|
||||
def test_append_numpy_bug_1681(self):
|
||||
|
||||
td = timedelta_range("1 days", "10 days", freq="2D")
|
||||
a = DataFrame()
|
||||
c = DataFrame({"A": "foo", "B": td}, index=td)
|
||||
str(c)
|
||||
|
||||
result = a.append(c)
|
||||
assert (result["B"] == td).all()
|
||||
|
||||
def test_fields(self):
|
||||
rng = timedelta_range("1 days, 10:11:12.100123456", periods=2, freq="s")
|
||||
tm.assert_index_equal(rng.days, Index([1, 1], dtype="int64"))
|
||||
tm.assert_index_equal(
|
||||
rng.seconds,
|
||||
Index([10 * 3600 + 11 * 60 + 12, 10 * 3600 + 11 * 60 + 13], dtype="int64"),
|
||||
)
|
||||
tm.assert_index_equal(
|
||||
rng.microseconds, Index([100 * 1000 + 123, 100 * 1000 + 123], dtype="int64")
|
||||
)
|
||||
tm.assert_index_equal(rng.nanoseconds, Index([456, 456], dtype="int64"))
|
||||
|
||||
msg = "'TimedeltaIndex' object has no attribute '{}'"
|
||||
with pytest.raises(AttributeError, match=msg.format("hours")):
|
||||
rng.hours
|
||||
with pytest.raises(AttributeError, match=msg.format("minutes")):
|
||||
rng.minutes
|
||||
with pytest.raises(AttributeError, match=msg.format("milliseconds")):
|
||||
rng.milliseconds
|
||||
|
||||
# with nat
|
||||
s = Series(rng)
|
||||
s[1] = np.nan
|
||||
|
||||
tm.assert_series_equal(s.dt.days, Series([1, np.nan], index=[0, 1]))
|
||||
tm.assert_series_equal(
|
||||
s.dt.seconds, Series([10 * 3600 + 11 * 60 + 12, np.nan], index=[0, 1])
|
||||
)
|
||||
|
||||
# preserve name (GH15589)
|
||||
rng.name = "name"
|
||||
assert rng.days.name == "name"
|
||||
|
||||
def test_freq_conversion(self):
|
||||
|
||||
# doc example
|
||||
|
||||
# series
|
||||
td = Series(date_range("20130101", periods=4)) - Series(
|
||||
date_range("20121201", periods=4)
|
||||
)
|
||||
td[2] += timedelta(minutes=5, seconds=3)
|
||||
td[3] = np.nan
|
||||
|
||||
result = td / np.timedelta64(1, "D")
|
||||
expected = Series([31, 31, (31 * 86400 + 5 * 60 + 3) / 86400.0, np.nan])
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = td.astype("timedelta64[D]")
|
||||
expected = Series([31, 31, 31, np.nan])
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = td / np.timedelta64(1, "s")
|
||||
expected = Series([31 * 86400, 31 * 86400, 31 * 86400 + 5 * 60 + 3, np.nan])
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
result = td.astype("timedelta64[s]")
|
||||
assert_series_equal(result, expected)
|
||||
|
||||
# tdi
|
||||
td = TimedeltaIndex(td)
|
||||
|
||||
result = td / np.timedelta64(1, "D")
|
||||
expected = Index([31, 31, (31 * 86400 + 5 * 60 + 3) / 86400.0, np.nan])
|
||||
assert_index_equal(result, expected)
|
||||
|
||||
result = td.astype("timedelta64[D]")
|
||||
expected = Index([31, 31, 31, np.nan])
|
||||
assert_index_equal(result, expected)
|
||||
|
||||
result = td / np.timedelta64(1, "s")
|
||||
expected = Index([31 * 86400, 31 * 86400, 31 * 86400 + 5 * 60 + 3, np.nan])
|
||||
assert_index_equal(result, expected)
|
||||
|
||||
result = td.astype("timedelta64[s]")
|
||||
assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("unit", ["Y", "y", "M"])
|
||||
def test_unit_m_y_deprecated(self, unit):
|
||||
with tm.assert_produces_warning(FutureWarning) as w:
|
||||
TimedeltaIndex([1, 3, 7], unit)
|
||||
msg = r".* units are deprecated .*"
|
||||
assert re.match(msg, str(w[0].message))
|
||||
|
||||
|
||||
class TestTimeSeries:
|
||||
def test_series_box_timedelta(self):
|
||||
rng = timedelta_range("1 day 1 s", periods=5, freq="h")
|
||||
s = Series(rng)
|
||||
assert isinstance(s[1], Timedelta)
|
||||
assert isinstance(s.iat[2], Timedelta)
|
@@ -0,0 +1,80 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import timedelta_range, to_timedelta
|
||||
import pandas.util.testing as tm
|
||||
|
||||
from pandas.tseries.offsets import Day, Second
|
||||
|
||||
|
||||
class TestTimedeltas:
|
||||
def test_timedelta_range(self):
|
||||
|
||||
expected = to_timedelta(np.arange(5), unit="D")
|
||||
result = timedelta_range("0 days", periods=5, freq="D")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
expected = to_timedelta(np.arange(11), unit="D")
|
||||
result = timedelta_range("0 days", "10 days", freq="D")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
expected = to_timedelta(np.arange(5), unit="D") + Second(2) + Day()
|
||||
result = timedelta_range("1 days, 00:00:02", "5 days, 00:00:02", freq="D")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
expected = to_timedelta([1, 3, 5, 7, 9], unit="D") + Second(2)
|
||||
result = timedelta_range("1 days, 00:00:02", periods=5, freq="2D")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
expected = to_timedelta(np.arange(50), unit="T") * 30
|
||||
result = timedelta_range("0 days", freq="30T", periods=50)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# GH 11776
|
||||
arr = np.arange(10).reshape(2, 5)
|
||||
df = pd.DataFrame(np.arange(10).reshape(2, 5))
|
||||
for arg in (arr, df):
|
||||
with pytest.raises(TypeError, match="1-d array"):
|
||||
to_timedelta(arg)
|
||||
for errors in ["ignore", "raise", "coerce"]:
|
||||
with pytest.raises(TypeError, match="1-d array"):
|
||||
to_timedelta(arg, errors=errors)
|
||||
|
||||
# issue10583
|
||||
df = pd.DataFrame(np.random.normal(size=(10, 4)))
|
||||
df.index = pd.timedelta_range(start="0s", periods=10, freq="s")
|
||||
expected = df.loc[pd.Timedelta("0s") :, :]
|
||||
result = df.loc["0s":, :]
|
||||
tm.assert_frame_equal(expected, result)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"periods, freq", [(3, "2D"), (5, "D"), (6, "19H12T"), (7, "16H"), (9, "12H")]
|
||||
)
|
||||
def test_linspace_behavior(self, periods, freq):
|
||||
# GH 20976
|
||||
result = timedelta_range(start="0 days", end="4 days", periods=periods)
|
||||
expected = timedelta_range(start="0 days", end="4 days", freq=freq)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_errors(self):
|
||||
# not enough params
|
||||
msg = (
|
||||
"Of the four parameters: start, end, periods, and freq, "
|
||||
"exactly three must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
timedelta_range(start="0 days")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
timedelta_range(end="5 days")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
timedelta_range(periods=2)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
timedelta_range()
|
||||
|
||||
# too many params
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
timedelta_range(start="0 days", end="5 days", periods=10, freq="H")
|
@@ -0,0 +1,221 @@
|
||||
from datetime import time, timedelta
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslib import iNaT
|
||||
|
||||
import pandas as pd
|
||||
from pandas import Series, TimedeltaIndex, isna, to_timedelta
|
||||
import pandas.util.testing as tm
|
||||
from pandas.util.testing import assert_series_equal
|
||||
|
||||
|
||||
class TestTimedeltas:
|
||||
def test_to_timedelta(self):
|
||||
def conv(v):
|
||||
return v.astype("m8[ns]")
|
||||
|
||||
d1 = np.timedelta64(1, "D")
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert to_timedelta("1 days 06:05:01.00003", box=False) == conv(
|
||||
d1
|
||||
+ np.timedelta64(6 * 3600 + 5 * 60 + 1, "s")
|
||||
+ np.timedelta64(30, "us")
|
||||
)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
assert to_timedelta("15.5us", box=False) == conv(
|
||||
np.timedelta64(15500, "ns")
|
||||
)
|
||||
|
||||
# empty string
|
||||
result = to_timedelta("", box=False)
|
||||
assert result.astype("int64") == iNaT
|
||||
|
||||
result = to_timedelta(["", ""])
|
||||
assert isna(result).all()
|
||||
|
||||
# pass thru
|
||||
result = to_timedelta(np.array([np.timedelta64(1, "s")]))
|
||||
expected = pd.Index(np.array([np.timedelta64(1, "s")]))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
# ints
|
||||
result = np.timedelta64(0, "ns")
|
||||
expected = to_timedelta(0, box=False)
|
||||
assert result == expected
|
||||
|
||||
# Series
|
||||
expected = Series([timedelta(days=1), timedelta(days=1, seconds=1)])
|
||||
result = to_timedelta(Series(["1d", "1days 00:00:01"]))
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
# with units
|
||||
result = TimedeltaIndex(
|
||||
[np.timedelta64(0, "ns"), np.timedelta64(10, "s").astype("m8[ns]")]
|
||||
)
|
||||
expected = to_timedelta([0, 10], unit="s")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
# single element conversion
|
||||
v = timedelta(seconds=1)
|
||||
result = to_timedelta(v, box=False)
|
||||
expected = np.timedelta64(timedelta(seconds=1))
|
||||
assert result == expected
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
v = np.timedelta64(timedelta(seconds=1))
|
||||
result = to_timedelta(v, box=False)
|
||||
expected = np.timedelta64(timedelta(seconds=1))
|
||||
assert result == expected
|
||||
|
||||
# arrays of various dtypes
|
||||
arr = np.array([1] * 5, dtype="int64")
|
||||
result = to_timedelta(arr, unit="s")
|
||||
expected = TimedeltaIndex([np.timedelta64(1, "s")] * 5)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
arr = np.array([1] * 5, dtype="int64")
|
||||
result = to_timedelta(arr, unit="m")
|
||||
expected = TimedeltaIndex([np.timedelta64(1, "m")] * 5)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
arr = np.array([1] * 5, dtype="int64")
|
||||
result = to_timedelta(arr, unit="h")
|
||||
expected = TimedeltaIndex([np.timedelta64(1, "h")] * 5)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
arr = np.array([1] * 5, dtype="timedelta64[s]")
|
||||
result = to_timedelta(arr)
|
||||
expected = TimedeltaIndex([np.timedelta64(1, "s")] * 5)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
arr = np.array([1] * 5, dtype="timedelta64[D]")
|
||||
result = to_timedelta(arr)
|
||||
expected = TimedeltaIndex([np.timedelta64(1, "D")] * 5)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
# Test with lists as input when box=false
|
||||
expected = np.array(np.arange(3) * 1000000000, dtype="timedelta64[ns]")
|
||||
result = to_timedelta(range(3), unit="s", box=False)
|
||||
tm.assert_numpy_array_equal(expected, result)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = to_timedelta(np.arange(3), unit="s", box=False)
|
||||
tm.assert_numpy_array_equal(expected, result)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
result = to_timedelta([0, 1, 2], unit="s", box=False)
|
||||
tm.assert_numpy_array_equal(expected, result)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
# Tests with fractional seconds as input:
|
||||
expected = np.array(
|
||||
[0, 500000000, 800000000, 1200000000], dtype="timedelta64[ns]"
|
||||
)
|
||||
result = to_timedelta([0.0, 0.5, 0.8, 1.2], unit="s", box=False)
|
||||
tm.assert_numpy_array_equal(expected, result)
|
||||
|
||||
def test_to_timedelta_invalid(self):
|
||||
|
||||
# bad value for errors parameter
|
||||
msg = "errors must be one of"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
to_timedelta(["foo"], errors="never")
|
||||
|
||||
# these will error
|
||||
msg = "invalid unit abbreviation: foo"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
to_timedelta([1, 2], unit="foo")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
to_timedelta(1, unit="foo")
|
||||
|
||||
# time not supported ATM
|
||||
msg = (
|
||||
"Value must be Timedelta, string, integer, float, timedelta or"
|
||||
" convertible"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
to_timedelta(time(second=1))
|
||||
assert to_timedelta(time(second=1), errors="coerce") is pd.NaT
|
||||
|
||||
msg = "unit abbreviation w/o a number"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
to_timedelta(["foo", "bar"])
|
||||
tm.assert_index_equal(
|
||||
TimedeltaIndex([pd.NaT, pd.NaT]),
|
||||
to_timedelta(["foo", "bar"], errors="coerce"),
|
||||
)
|
||||
|
||||
tm.assert_index_equal(
|
||||
TimedeltaIndex(["1 day", pd.NaT, "1 min"]),
|
||||
to_timedelta(["1 day", "bar", "1 min"], errors="coerce"),
|
||||
)
|
||||
|
||||
# gh-13613: these should not error because errors='ignore'
|
||||
invalid_data = "apple"
|
||||
assert invalid_data == to_timedelta(invalid_data, errors="ignore")
|
||||
|
||||
invalid_data = ["apple", "1 days"]
|
||||
tm.assert_numpy_array_equal(
|
||||
np.array(invalid_data, dtype=object),
|
||||
to_timedelta(invalid_data, errors="ignore"),
|
||||
)
|
||||
|
||||
invalid_data = pd.Index(["apple", "1 days"])
|
||||
tm.assert_index_equal(invalid_data, to_timedelta(invalid_data, errors="ignore"))
|
||||
|
||||
invalid_data = Series(["apple", "1 days"])
|
||||
tm.assert_series_equal(
|
||||
invalid_data, to_timedelta(invalid_data, errors="ignore")
|
||||
)
|
||||
|
||||
def test_to_timedelta_via_apply(self):
|
||||
# GH 5458
|
||||
expected = Series([np.timedelta64(1, "s")])
|
||||
result = Series(["00:00:01"]).apply(to_timedelta)
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
result = Series([to_timedelta("00:00:01")])
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
def test_to_timedelta_on_missing_values(self):
|
||||
# GH5438
|
||||
timedelta_NaT = np.timedelta64("NaT")
|
||||
|
||||
actual = pd.to_timedelta(Series(["00:00:01", np.nan]))
|
||||
expected = Series(
|
||||
[np.timedelta64(1000000000, "ns"), timedelta_NaT], dtype="<m8[ns]"
|
||||
)
|
||||
assert_series_equal(actual, expected)
|
||||
|
||||
actual = pd.to_timedelta(Series(["00:00:01", pd.NaT]))
|
||||
assert_series_equal(actual, expected)
|
||||
|
||||
actual = pd.to_timedelta(np.nan)
|
||||
assert actual.value == timedelta_NaT.astype("int64")
|
||||
|
||||
actual = pd.to_timedelta(pd.NaT)
|
||||
assert actual.value == timedelta_NaT.astype("int64")
|
||||
|
||||
def test_to_timedelta_float(self):
|
||||
# https://github.com/pandas-dev/pandas/issues/25077
|
||||
arr = np.arange(0, 1, 1e-6)[-10:]
|
||||
result = pd.to_timedelta(arr, unit="s")
|
||||
expected_asi8 = np.arange(999990000, int(1e9), 1000, dtype="int64")
|
||||
tm.assert_numpy_array_equal(result.asi8, expected_asi8)
|
||||
|
||||
def test_to_timedelta_box_deprecated(self):
|
||||
result = np.timedelta64(0, "ns")
|
||||
|
||||
# Deprecated - see GH24416
|
||||
with tm.assert_produces_warning(FutureWarning):
|
||||
to_timedelta(0, box=False)
|
||||
|
||||
expected = to_timedelta(0).to_timedelta64()
|
||||
assert result == expected
|
Reference in New Issue
Block a user