virtuelle Umgebungen teil20 und teil20a
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,138 @@
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
Series,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_asfreq(self):
|
||||
pi1 = period_range(freq="A", start="1/1/2001", end="1/1/2001")
|
||||
pi2 = period_range(freq="Q", start="1/1/2001", end="1/1/2001")
|
||||
pi3 = period_range(freq="M", start="1/1/2001", end="1/1/2001")
|
||||
pi4 = period_range(freq="D", start="1/1/2001", end="1/1/2001")
|
||||
pi5 = period_range(freq="H", start="1/1/2001", end="1/1/2001 00:00")
|
||||
pi6 = period_range(freq="Min", start="1/1/2001", end="1/1/2001 00:00")
|
||||
pi7 = period_range(freq="S", start="1/1/2001", end="1/1/2001 00:00:00")
|
||||
|
||||
assert pi1.asfreq("Q", "S") == pi2
|
||||
assert pi1.asfreq("Q", "s") == pi2
|
||||
assert pi1.asfreq("M", "start") == pi3
|
||||
assert pi1.asfreq("D", "StarT") == pi4
|
||||
assert pi1.asfreq("H", "beGIN") == pi5
|
||||
assert pi1.asfreq("Min", "S") == pi6
|
||||
assert pi1.asfreq("S", "S") == pi7
|
||||
|
||||
assert pi2.asfreq("A", "S") == pi1
|
||||
assert pi2.asfreq("M", "S") == pi3
|
||||
assert pi2.asfreq("D", "S") == pi4
|
||||
assert pi2.asfreq("H", "S") == pi5
|
||||
assert pi2.asfreq("Min", "S") == pi6
|
||||
assert pi2.asfreq("S", "S") == pi7
|
||||
|
||||
assert pi3.asfreq("A", "S") == pi1
|
||||
assert pi3.asfreq("Q", "S") == pi2
|
||||
assert pi3.asfreq("D", "S") == pi4
|
||||
assert pi3.asfreq("H", "S") == pi5
|
||||
assert pi3.asfreq("Min", "S") == pi6
|
||||
assert pi3.asfreq("S", "S") == pi7
|
||||
|
||||
assert pi4.asfreq("A", "S") == pi1
|
||||
assert pi4.asfreq("Q", "S") == pi2
|
||||
assert pi4.asfreq("M", "S") == pi3
|
||||
assert pi4.asfreq("H", "S") == pi5
|
||||
assert pi4.asfreq("Min", "S") == pi6
|
||||
assert pi4.asfreq("S", "S") == pi7
|
||||
|
||||
assert pi5.asfreq("A", "S") == pi1
|
||||
assert pi5.asfreq("Q", "S") == pi2
|
||||
assert pi5.asfreq("M", "S") == pi3
|
||||
assert pi5.asfreq("D", "S") == pi4
|
||||
assert pi5.asfreq("Min", "S") == pi6
|
||||
assert pi5.asfreq("S", "S") == pi7
|
||||
|
||||
assert pi6.asfreq("A", "S") == pi1
|
||||
assert pi6.asfreq("Q", "S") == pi2
|
||||
assert pi6.asfreq("M", "S") == pi3
|
||||
assert pi6.asfreq("D", "S") == pi4
|
||||
assert pi6.asfreq("H", "S") == pi5
|
||||
assert pi6.asfreq("S", "S") == pi7
|
||||
|
||||
assert pi7.asfreq("A", "S") == pi1
|
||||
assert pi7.asfreq("Q", "S") == pi2
|
||||
assert pi7.asfreq("M", "S") == pi3
|
||||
assert pi7.asfreq("D", "S") == pi4
|
||||
assert pi7.asfreq("H", "S") == pi5
|
||||
assert pi7.asfreq("Min", "S") == pi6
|
||||
|
||||
msg = "How must be one of S or E"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
pi7.asfreq("T", "foo")
|
||||
result1 = pi1.asfreq("3M")
|
||||
result2 = pi1.asfreq("M")
|
||||
expected = period_range(freq="M", start="2001-12", end="2001-12")
|
||||
tm.assert_numpy_array_equal(result1.asi8, expected.asi8)
|
||||
assert result1.freqstr == "3M"
|
||||
tm.assert_numpy_array_equal(result2.asi8, expected.asi8)
|
||||
assert result2.freqstr == "M"
|
||||
|
||||
def test_asfreq_nat(self):
|
||||
idx = PeriodIndex(["2011-01", "2011-02", "NaT", "2011-04"], freq="M")
|
||||
result = idx.asfreq(freq="Q")
|
||||
expected = PeriodIndex(["2011Q1", "2011Q1", "NaT", "2011Q2"], freq="Q")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize("freq", ["D", "3D"])
|
||||
def test_asfreq_mult_pi(self, freq):
|
||||
pi = PeriodIndex(["2001-01", "2001-02", "NaT", "2001-03"], freq="2M")
|
||||
|
||||
result = pi.asfreq(freq)
|
||||
exp = PeriodIndex(["2001-02-28", "2001-03-31", "NaT", "2001-04-30"], freq=freq)
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == exp.freq
|
||||
|
||||
result = pi.asfreq(freq, how="S")
|
||||
exp = PeriodIndex(["2001-01-01", "2001-02-01", "NaT", "2001-03-01"], freq=freq)
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == exp.freq
|
||||
|
||||
def test_asfreq_combined_pi(self):
|
||||
pi = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq="H")
|
||||
exp = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq="25H")
|
||||
for freq, how in zip(["1D1H", "1H1D"], ["S", "E"]):
|
||||
result = pi.asfreq(freq, how=how)
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == exp.freq
|
||||
|
||||
for freq in ["1D1H", "1H1D"]:
|
||||
pi = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq=freq)
|
||||
result = pi.asfreq("H")
|
||||
exp = PeriodIndex(["2001-01-02 00:00", "2001-01-03 02:00", "NaT"], freq="H")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == exp.freq
|
||||
|
||||
pi = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq=freq)
|
||||
result = pi.asfreq("H", how="S")
|
||||
exp = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq="H")
|
||||
tm.assert_index_equal(result, exp)
|
||||
assert result.freq == exp.freq
|
||||
|
||||
def test_astype_asfreq(self):
|
||||
pi1 = PeriodIndex(["2011-01-01", "2011-02-01", "2011-03-01"], freq="D")
|
||||
exp = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M")
|
||||
tm.assert_index_equal(pi1.asfreq("M"), exp)
|
||||
tm.assert_index_equal(pi1.astype("period[M]"), exp)
|
||||
|
||||
exp = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="3M")
|
||||
tm.assert_index_equal(pi1.asfreq("3M"), exp)
|
||||
tm.assert_index_equal(pi1.astype("period[3M]"), exp)
|
||||
|
||||
def test_asfreq_with_different_n(self):
|
||||
ser = Series([1, 2], index=PeriodIndex(["2020-01", "2020-03"], freq="2M"))
|
||||
result = ser.asfreq("M")
|
||||
|
||||
excepted = Series([1, 2], index=PeriodIndex(["2020-02", "2020-04"], freq="M"))
|
||||
tm.assert_series_equal(result, excepted)
|
@@ -0,0 +1,148 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
CategoricalIndex,
|
||||
DatetimeIndex,
|
||||
Index,
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndexAsType:
|
||||
@pytest.mark.parametrize("dtype", [float, "timedelta64", "timedelta64[ns]"])
|
||||
def test_astype_raises(self, dtype):
|
||||
# GH#13149, GH#13209
|
||||
idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.nan], freq="D")
|
||||
msg = "Cannot cast PeriodIndex to dtype"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx.astype(dtype)
|
||||
|
||||
def test_astype_conversion(self):
|
||||
# GH#13149, GH#13209
|
||||
idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.nan], freq="D", name="idx")
|
||||
|
||||
result = idx.astype(object)
|
||||
expected = Index(
|
||||
[Period("2016-05-16", freq="D")] + [Period(NaT, freq="D")] * 3,
|
||||
dtype="object",
|
||||
name="idx",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.astype(np.int64)
|
||||
expected = Index(
|
||||
[16937] + [-9223372036854775808] * 3, dtype=np.int64, name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.astype(str)
|
||||
expected = Index([str(x) for x in idx], name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
idx = period_range("1990", "2009", freq="A", name="idx")
|
||||
result = idx.astype("i8")
|
||||
tm.assert_index_equal(result, Index(idx.asi8, name="idx"))
|
||||
tm.assert_numpy_array_equal(result.values, idx.asi8)
|
||||
|
||||
def test_astype_uint(self):
|
||||
arr = period_range("2000", periods=2, name="idx")
|
||||
|
||||
with pytest.raises(TypeError, match=r"Do obj.astype\('int64'\)"):
|
||||
arr.astype("uint64")
|
||||
with pytest.raises(TypeError, match=r"Do obj.astype\('int64'\)"):
|
||||
arr.astype("uint32")
|
||||
|
||||
def test_astype_object(self):
|
||||
idx = PeriodIndex([], freq="M")
|
||||
|
||||
exp = np.array([], dtype=object)
|
||||
tm.assert_numpy_array_equal(idx.astype(object).values, exp)
|
||||
tm.assert_numpy_array_equal(idx._mpl_repr(), exp)
|
||||
|
||||
idx = PeriodIndex(["2011-01", NaT], freq="M")
|
||||
|
||||
exp = np.array([Period("2011-01", freq="M"), NaT], dtype=object)
|
||||
tm.assert_numpy_array_equal(idx.astype(object).values, exp)
|
||||
tm.assert_numpy_array_equal(idx._mpl_repr(), exp)
|
||||
|
||||
exp = np.array([Period("2011-01-01", freq="D"), NaT], dtype=object)
|
||||
idx = PeriodIndex(["2011-01-01", NaT], freq="D")
|
||||
tm.assert_numpy_array_equal(idx.astype(object).values, exp)
|
||||
tm.assert_numpy_array_equal(idx._mpl_repr(), exp)
|
||||
|
||||
# TODO: de-duplicate this version (from test_ops) with the one above
|
||||
# (from test_period)
|
||||
def test_astype_object2(self):
|
||||
idx = period_range(start="2013-01-01", periods=4, freq="M", name="idx")
|
||||
expected_list = [
|
||||
Period("2013-01-31", freq="M"),
|
||||
Period("2013-02-28", freq="M"),
|
||||
Period("2013-03-31", freq="M"),
|
||||
Period("2013-04-30", freq="M"),
|
||||
]
|
||||
expected = Index(expected_list, dtype=object, name="idx")
|
||||
result = idx.astype(object)
|
||||
assert isinstance(result, Index)
|
||||
assert result.dtype == object
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert idx.tolist() == expected_list
|
||||
|
||||
idx = PeriodIndex(
|
||||
["2013-01-01", "2013-01-02", "NaT", "2013-01-04"], freq="D", name="idx"
|
||||
)
|
||||
expected_list = [
|
||||
Period("2013-01-01", freq="D"),
|
||||
Period("2013-01-02", freq="D"),
|
||||
Period("NaT", freq="D"),
|
||||
Period("2013-01-04", freq="D"),
|
||||
]
|
||||
expected = Index(expected_list, dtype=object, name="idx")
|
||||
result = idx.astype(object)
|
||||
assert isinstance(result, Index)
|
||||
assert result.dtype == object
|
||||
tm.assert_index_equal(result, expected)
|
||||
for i in [0, 1, 3]:
|
||||
assert result[i] == expected[i]
|
||||
assert result[2] is NaT
|
||||
assert result.name == expected.name
|
||||
|
||||
result_list = idx.tolist()
|
||||
for i in [0, 1, 3]:
|
||||
assert result_list[i] == expected_list[i]
|
||||
assert result_list[2] is NaT
|
||||
|
||||
def test_astype_category(self):
|
||||
obj = period_range("2000", periods=2, name="idx")
|
||||
result = obj.astype("category")
|
||||
expected = CategoricalIndex(
|
||||
[Period("2000-01-01", freq="D"), Period("2000-01-02", freq="D")], name="idx"
|
||||
)
|
||||
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 = period_range("2000", periods=2, name="idx")
|
||||
result = obj.astype(bool)
|
||||
expected = Index(np.array([True, True]), name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = obj._data.astype(bool)
|
||||
expected = np.array([True, True])
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
def test_period_astype_to_timestamp(self):
|
||||
pi = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M")
|
||||
|
||||
exp = DatetimeIndex(["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern")
|
||||
res = pi.astype("datetime64[ns, US/Eastern]")
|
||||
tm.assert_index_equal(res, exp)
|
||||
assert res.freq == exp.freq
|
@@ -0,0 +1,54 @@
|
||||
import numpy as np
|
||||
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
factorize,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestFactorize:
|
||||
def test_factorize(self):
|
||||
idx1 = PeriodIndex(
|
||||
["2014-01", "2014-01", "2014-02", "2014-02", "2014-03", "2014-03"], freq="M"
|
||||
)
|
||||
|
||||
exp_arr = np.array([0, 0, 1, 1, 2, 2], dtype=np.intp)
|
||||
exp_idx = PeriodIndex(["2014-01", "2014-02", "2014-03"], freq="M")
|
||||
|
||||
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)
|
||||
|
||||
idx2 = PeriodIndex(
|
||||
["2014-03", "2014-03", "2014-02", "2014-01", "2014-03", "2014-01"], freq="M"
|
||||
)
|
||||
|
||||
exp_arr = np.array([2, 2, 1, 0, 2, 0], dtype=np.intp)
|
||||
arr, idx = idx2.factorize(sort=True)
|
||||
tm.assert_numpy_array_equal(arr, exp_arr)
|
||||
tm.assert_index_equal(idx, exp_idx)
|
||||
|
||||
exp_arr = np.array([0, 0, 1, 2, 0, 2], dtype=np.intp)
|
||||
exp_idx = PeriodIndex(["2014-03", "2014-02", "2014-01"], freq="M")
|
||||
arr, idx = idx2.factorize()
|
||||
tm.assert_numpy_array_equal(arr, exp_arr)
|
||||
tm.assert_index_equal(idx, exp_idx)
|
||||
|
||||
def test_factorize_complex(self): # TODO: WTF is this test doing here?s
|
||||
# GH 17927
|
||||
array = [1, 2, 2 + 1j]
|
||||
msg = "factorize with argument that is not not a Series"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
labels, uniques = factorize(array)
|
||||
|
||||
expected_labels = np.array([0, 1, 2], dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(labels, expected_labels)
|
||||
|
||||
# Should return a complex dtype in the future
|
||||
expected_uniques = np.array([(1 + 0j), (2 + 0j), (2 + 1j)], dtype=object)
|
||||
tm.assert_numpy_array_equal(uniques, expected_uniques)
|
@@ -0,0 +1,41 @@
|
||||
from pandas import (
|
||||
Index,
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestFillNA:
|
||||
def test_fillna_period(self):
|
||||
# GH#11343
|
||||
idx = PeriodIndex(["2011-01-01 09:00", NaT, "2011-01-01 11:00"], freq="H")
|
||||
|
||||
exp = PeriodIndex(
|
||||
["2011-01-01 09:00", "2011-01-01 10:00", "2011-01-01 11:00"], freq="H"
|
||||
)
|
||||
result = idx.fillna(Period("2011-01-01 10:00", freq="H"))
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
exp = Index(
|
||||
[
|
||||
Period("2011-01-01 09:00", freq="H"),
|
||||
"x",
|
||||
Period("2011-01-01 11:00", freq="H"),
|
||||
],
|
||||
dtype=object,
|
||||
)
|
||||
result = idx.fillna("x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
exp = Index(
|
||||
[
|
||||
Period("2011-01-01 09:00", freq="H"),
|
||||
Period("2011-01-01", freq="D"),
|
||||
Period("2011-01-01 11:00", freq="H"),
|
||||
],
|
||||
dtype=object,
|
||||
)
|
||||
result = idx.fillna(Period("2011-01-01", freq="D"))
|
||||
tm.assert_index_equal(result, exp)
|
@@ -0,0 +1,18 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
NaT,
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestInsert:
|
||||
@pytest.mark.parametrize("na", [np.nan, NaT, None])
|
||||
def test_insert(self, na):
|
||||
# GH#18295 (test missing)
|
||||
expected = PeriodIndex(["2017Q1", NaT, "2017Q2", "2017Q3", "2017Q4"], freq="Q")
|
||||
result = period_range("2017Q1", periods=4, freq="Q").insert(1, na)
|
||||
tm.assert_index_equal(result, expected)
|
@@ -0,0 +1,23 @@
|
||||
import pytest
|
||||
|
||||
from pandas import PeriodIndex
|
||||
|
||||
|
||||
def test_is_full():
|
||||
index = PeriodIndex([2005, 2007, 2009], freq="A")
|
||||
assert not index.is_full
|
||||
|
||||
index = PeriodIndex([2005, 2006, 2007], freq="A")
|
||||
assert index.is_full
|
||||
|
||||
index = PeriodIndex([2005, 2005, 2007], freq="A")
|
||||
assert not index.is_full
|
||||
|
||||
index = PeriodIndex([2005, 2005, 2006], freq="A")
|
||||
assert index.is_full
|
||||
|
||||
index = PeriodIndex([2006, 2005, 2005], freq="A")
|
||||
with pytest.raises(ValueError, match="Index is not monotonic"):
|
||||
index.is_full
|
||||
|
||||
assert index[:0].is_full
|
@@ -0,0 +1,26 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestRepeat:
|
||||
@pytest.mark.parametrize("use_numpy", [True, False])
|
||||
@pytest.mark.parametrize(
|
||||
"index",
|
||||
[
|
||||
period_range("2000-01-01", periods=3, freq="D"),
|
||||
period_range("2001-01-01", periods=3, freq="2D"),
|
||||
PeriodIndex(["2001-01", "NaT", "2003-01"], freq="M"),
|
||||
],
|
||||
)
|
||||
def test_repeat_freqstr(self, index, use_numpy):
|
||||
# GH#10183
|
||||
expected = PeriodIndex([per for per in index for _ in range(3)])
|
||||
result = np.repeat(index, 3) if use_numpy else index.repeat(3)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freqstr == index.freqstr
|
@@ -0,0 +1,122 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndexShift:
|
||||
# ---------------------------------------------------------------
|
||||
# PeriodIndex.shift is used by __add__ and __sub__
|
||||
|
||||
def test_pi_shift_ndarray(self):
|
||||
idx = PeriodIndex(
|
||||
["2011-01", "2011-02", "NaT", "2011-04"], freq="M", name="idx"
|
||||
)
|
||||
result = idx.shift(np.array([1, 2, 3, 4]))
|
||||
expected = PeriodIndex(
|
||||
["2011-02", "2011-04", "NaT", "2011-08"], freq="M", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.shift(np.array([1, -2, 3, -4]))
|
||||
expected = PeriodIndex(
|
||||
["2011-02", "2010-12", "NaT", "2010-12"], freq="M", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_shift(self):
|
||||
pi1 = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="A", start="1/1/2002", end="12/1/2010")
|
||||
|
||||
tm.assert_index_equal(pi1.shift(0), pi1)
|
||||
|
||||
assert len(pi1) == len(pi2)
|
||||
tm.assert_index_equal(pi1.shift(1), pi2)
|
||||
|
||||
pi1 = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="A", start="1/1/2000", end="12/1/2008")
|
||||
assert len(pi1) == len(pi2)
|
||||
tm.assert_index_equal(pi1.shift(-1), pi2)
|
||||
|
||||
pi1 = period_range(freq="M", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="M", start="2/1/2001", end="1/1/2010")
|
||||
assert len(pi1) == len(pi2)
|
||||
tm.assert_index_equal(pi1.shift(1), pi2)
|
||||
|
||||
pi1 = period_range(freq="M", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="M", start="12/1/2000", end="11/1/2009")
|
||||
assert len(pi1) == len(pi2)
|
||||
tm.assert_index_equal(pi1.shift(-1), pi2)
|
||||
|
||||
pi1 = period_range(freq="D", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="D", start="1/2/2001", end="12/2/2009")
|
||||
assert len(pi1) == len(pi2)
|
||||
tm.assert_index_equal(pi1.shift(1), pi2)
|
||||
|
||||
pi1 = period_range(freq="D", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="D", start="12/31/2000", end="11/30/2009")
|
||||
assert len(pi1) == len(pi2)
|
||||
tm.assert_index_equal(pi1.shift(-1), pi2)
|
||||
|
||||
def test_shift_corner_cases(self):
|
||||
# GH#9903
|
||||
idx = PeriodIndex([], name="xxx", freq="H")
|
||||
|
||||
msg = "`freq` argument is not supported for PeriodIndex.shift"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
# period shift doesn't accept freq
|
||||
idx.shift(1, freq="H")
|
||||
|
||||
tm.assert_index_equal(idx.shift(0), idx)
|
||||
tm.assert_index_equal(idx.shift(3), idx)
|
||||
|
||||
idx = PeriodIndex(
|
||||
["2011-01-01 10:00", "2011-01-01 11:00", "2011-01-01 12:00"],
|
||||
name="xxx",
|
||||
freq="H",
|
||||
)
|
||||
tm.assert_index_equal(idx.shift(0), idx)
|
||||
exp = PeriodIndex(
|
||||
["2011-01-01 13:00", "2011-01-01 14:00", "2011-01-01 15:00"],
|
||||
name="xxx",
|
||||
freq="H",
|
||||
)
|
||||
tm.assert_index_equal(idx.shift(3), exp)
|
||||
exp = PeriodIndex(
|
||||
["2011-01-01 07:00", "2011-01-01 08:00", "2011-01-01 09:00"],
|
||||
name="xxx",
|
||||
freq="H",
|
||||
)
|
||||
tm.assert_index_equal(idx.shift(-3), exp)
|
||||
|
||||
def test_shift_nat(self):
|
||||
idx = PeriodIndex(
|
||||
["2011-01", "2011-02", "NaT", "2011-04"], freq="M", name="idx"
|
||||
)
|
||||
result = idx.shift(1)
|
||||
expected = PeriodIndex(
|
||||
["2011-02", "2011-03", "NaT", "2011-05"], freq="M", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
|
||||
def test_shift_gh8083(self):
|
||||
# test shift for PeriodIndex
|
||||
# GH#8083
|
||||
drange = period_range("20130101", periods=5, freq="D")
|
||||
result = drange.shift(1)
|
||||
expected = PeriodIndex(
|
||||
["2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06"],
|
||||
freq="D",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_shift_periods(self):
|
||||
# GH #22458 : argument 'n' was deprecated in favor of 'periods'
|
||||
idx = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
tm.assert_index_equal(idx.shift(periods=0), idx)
|
||||
tm.assert_index_equal(idx.shift(0), idx)
|
@@ -0,0 +1,132 @@
|
||||
from datetime import datetime
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
DatetimeIndex,
|
||||
NaT,
|
||||
PeriodIndex,
|
||||
Timedelta,
|
||||
Timestamp,
|
||||
date_range,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestToTimestamp:
|
||||
def test_to_timestamp_non_contiguous(self):
|
||||
# GH#44100
|
||||
dti = date_range("2021-10-18", periods=9, freq="D")
|
||||
pi = dti.to_period()
|
||||
|
||||
result = pi[::2].to_timestamp()
|
||||
expected = dti[::2]
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = pi._data[::2].to_timestamp()
|
||||
expected = dti._data[::2]
|
||||
# TODO: can we get the freq to round-trip?
|
||||
tm.assert_datetime_array_equal(result, expected, check_freq=False)
|
||||
|
||||
result = pi[::-1].to_timestamp()
|
||||
expected = dti[::-1]
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = pi._data[::-1].to_timestamp()
|
||||
expected = dti._data[::-1]
|
||||
tm.assert_datetime_array_equal(result, expected, check_freq=False)
|
||||
|
||||
result = pi[::2][::-1].to_timestamp()
|
||||
expected = dti[::2][::-1]
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = pi._data[::2][::-1].to_timestamp()
|
||||
expected = dti._data[::2][::-1]
|
||||
tm.assert_datetime_array_equal(result, expected, check_freq=False)
|
||||
|
||||
def test_to_timestamp_freq(self):
|
||||
idx = period_range("2017", periods=12, freq="A-DEC")
|
||||
result = idx.to_timestamp()
|
||||
expected = date_range("2017", periods=12, freq="AS-JAN")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_to_timestamp_pi_nat(self):
|
||||
# GH#7228
|
||||
index = PeriodIndex(["NaT", "2011-01", "2011-02"], freq="M", name="idx")
|
||||
|
||||
result = index.to_timestamp("D")
|
||||
expected = DatetimeIndex(
|
||||
[NaT, datetime(2011, 1, 1), datetime(2011, 2, 1)], name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == "idx"
|
||||
|
||||
result2 = result.to_period(freq="M")
|
||||
tm.assert_index_equal(result2, index)
|
||||
assert result2.name == "idx"
|
||||
|
||||
result3 = result.to_period(freq="3M")
|
||||
exp = PeriodIndex(["NaT", "2011-01", "2011-02"], freq="3M", name="idx")
|
||||
tm.assert_index_equal(result3, exp)
|
||||
assert result3.freqstr == "3M"
|
||||
|
||||
msg = "Frequency must be positive, because it represents span: -2A"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
result.to_period(freq="-2A")
|
||||
|
||||
def test_to_timestamp_preserve_name(self):
|
||||
index = period_range(freq="A", start="1/1/2001", end="12/1/2009", name="foo")
|
||||
assert index.name == "foo"
|
||||
|
||||
conv = index.to_timestamp("D")
|
||||
assert conv.name == "foo"
|
||||
|
||||
def test_to_timestamp_quarterly_bug(self):
|
||||
years = np.arange(1960, 2000).repeat(4)
|
||||
quarters = np.tile(list(range(1, 5)), 40)
|
||||
|
||||
pindex = PeriodIndex(year=years, quarter=quarters)
|
||||
|
||||
stamps = pindex.to_timestamp("D", "end")
|
||||
expected = DatetimeIndex([x.to_timestamp("D", "end") for x in pindex])
|
||||
tm.assert_index_equal(stamps, expected)
|
||||
assert stamps.freq == expected.freq
|
||||
|
||||
def test_to_timestamp_pi_mult(self):
|
||||
idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="2M", name="idx")
|
||||
|
||||
result = idx.to_timestamp()
|
||||
expected = DatetimeIndex(["2011-01-01", "NaT", "2011-02-01"], name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.to_timestamp(how="E")
|
||||
expected = DatetimeIndex(["2011-02-28", "NaT", "2011-03-31"], name="idx")
|
||||
expected = expected + Timedelta(1, "D") - Timedelta(1, "ns")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_to_timestamp_pi_combined(self):
|
||||
idx = period_range(start="2011", periods=2, freq="1D1H", name="idx")
|
||||
|
||||
result = idx.to_timestamp()
|
||||
expected = DatetimeIndex(["2011-01-01 00:00", "2011-01-02 01:00"], name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.to_timestamp(how="E")
|
||||
expected = DatetimeIndex(
|
||||
["2011-01-02 00:59:59", "2011-01-03 01:59:59"], name="idx"
|
||||
)
|
||||
expected = expected + Timedelta(1, "s") - Timedelta(1, "ns")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.to_timestamp(how="E", freq="H")
|
||||
expected = DatetimeIndex(["2011-01-02 00:00", "2011-01-03 01:00"], name="idx")
|
||||
expected = expected + Timedelta(1, "h") - Timedelta(1, "ns")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_to_timestamp_1703(self):
|
||||
index = period_range("1/1/2012", periods=4, freq="D")
|
||||
|
||||
result = index.to_timestamp()
|
||||
assert result[0] == Timestamp("1/1/2012")
|
@@ -0,0 +1,567 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs.period import IncompatibleFrequency
|
||||
|
||||
from pandas.core.dtypes.dtypes import PeriodDtype
|
||||
|
||||
from pandas import (
|
||||
Index,
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
Series,
|
||||
date_range,
|
||||
offsets,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
from pandas.core.arrays import PeriodArray
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_construction_base_constructor(self):
|
||||
# GH 13664
|
||||
arr = [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="M")]
|
||||
tm.assert_index_equal(Index(arr), PeriodIndex(arr))
|
||||
tm.assert_index_equal(Index(np.array(arr)), PeriodIndex(np.array(arr)))
|
||||
|
||||
arr = [np.nan, NaT, Period("2011-03", freq="M")]
|
||||
tm.assert_index_equal(Index(arr), PeriodIndex(arr))
|
||||
tm.assert_index_equal(Index(np.array(arr)), PeriodIndex(np.array(arr)))
|
||||
|
||||
arr = [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="D")]
|
||||
tm.assert_index_equal(Index(arr), Index(arr, dtype=object))
|
||||
|
||||
tm.assert_index_equal(Index(np.array(arr)), Index(np.array(arr), dtype=object))
|
||||
|
||||
def test_base_constructor_with_period_dtype(self):
|
||||
dtype = PeriodDtype("D")
|
||||
values = ["2011-01-01", "2012-03-04", "2014-05-01"]
|
||||
result = Index(values, dtype=dtype)
|
||||
|
||||
expected = PeriodIndex(values, dtype=dtype)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"values_constructor", [list, np.array, PeriodIndex, PeriodArray._from_sequence]
|
||||
)
|
||||
def test_index_object_dtype(self, values_constructor):
|
||||
# Index(periods, dtype=object) is an Index (not an PeriodIndex)
|
||||
periods = [
|
||||
Period("2011-01", freq="M"),
|
||||
NaT,
|
||||
Period("2011-03", freq="M"),
|
||||
]
|
||||
values = values_constructor(periods)
|
||||
result = Index(values, dtype=object)
|
||||
|
||||
assert type(result) is Index
|
||||
tm.assert_numpy_array_equal(result.values, np.array(values))
|
||||
|
||||
def test_constructor_use_start_freq(self):
|
||||
# GH #1118
|
||||
msg1 = "Period with BDay freq is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg1):
|
||||
p = Period("4/2/2012", freq="B")
|
||||
msg2 = r"PeriodDtype\[B\] is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
expected = period_range(start="4/2/2012", periods=10, freq="B")
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
index = period_range(start=p, periods=10)
|
||||
tm.assert_index_equal(index, expected)
|
||||
|
||||
def test_constructor_field_arrays(self):
|
||||
# GH #1264
|
||||
|
||||
years = np.arange(1990, 2010).repeat(4)[2:-2]
|
||||
quarters = np.tile(np.arange(1, 5), 20)[2:-2]
|
||||
|
||||
index = PeriodIndex(year=years, quarter=quarters, freq="Q-DEC")
|
||||
expected = period_range("1990Q3", "2009Q2", freq="Q-DEC")
|
||||
tm.assert_index_equal(index, expected)
|
||||
|
||||
index2 = PeriodIndex(year=years, quarter=quarters, freq="2Q-DEC")
|
||||
tm.assert_numpy_array_equal(index.asi8, index2.asi8)
|
||||
|
||||
index = PeriodIndex(year=years, quarter=quarters)
|
||||
tm.assert_index_equal(index, expected)
|
||||
|
||||
years = [2007, 2007, 2007]
|
||||
months = [1, 2]
|
||||
|
||||
msg = "Mismatched Period array lengths"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(year=years, month=months, freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(year=years, month=months, freq="2M")
|
||||
|
||||
years = [2007, 2007, 2007]
|
||||
months = [1, 2, 3]
|
||||
idx = PeriodIndex(year=years, month=months, freq="M")
|
||||
exp = period_range("2007-01", periods=3, freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
def test_constructor_U(self):
|
||||
# U was used as undefined period
|
||||
with pytest.raises(ValueError, match="Invalid frequency: X"):
|
||||
period_range("2007-1-1", periods=500, freq="X")
|
||||
|
||||
def test_constructor_nano(self):
|
||||
idx = period_range(
|
||||
start=Period(ordinal=1, freq="N"), end=Period(ordinal=4, freq="N"), freq="N"
|
||||
)
|
||||
exp = PeriodIndex(
|
||||
[
|
||||
Period(ordinal=1, freq="N"),
|
||||
Period(ordinal=2, freq="N"),
|
||||
Period(ordinal=3, freq="N"),
|
||||
Period(ordinal=4, freq="N"),
|
||||
],
|
||||
freq="N",
|
||||
)
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
def test_constructor_arrays_negative_year(self):
|
||||
years = np.arange(1960, 2000, dtype=np.int64).repeat(4)
|
||||
quarters = np.tile(np.array([1, 2, 3, 4], dtype=np.int64), 40)
|
||||
|
||||
pindex = PeriodIndex(year=years, quarter=quarters)
|
||||
|
||||
tm.assert_index_equal(pindex.year, Index(years))
|
||||
tm.assert_index_equal(pindex.quarter, Index(quarters))
|
||||
|
||||
def test_constructor_invalid_quarters(self):
|
||||
msg = "Quarter must be 1 <= q <= 4"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(year=range(2000, 2004), quarter=list(range(4)), freq="Q-DEC")
|
||||
|
||||
def test_constructor_corner(self):
|
||||
result = period_range("2007-01", periods=10.5, freq="M")
|
||||
exp = period_range("2007-01", periods=10, freq="M")
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_constructor_with_without_freq(self):
|
||||
# GH53687
|
||||
start = Period("2002-01-01 00:00", freq="30T")
|
||||
exp = period_range(start=start, periods=5, freq=start.freq)
|
||||
result = period_range(start=start, periods=5)
|
||||
tm.assert_index_equal(exp, result)
|
||||
|
||||
def test_constructor_fromarraylike(self):
|
||||
idx = period_range("2007-01", periods=20, freq="M")
|
||||
|
||||
# values is an array of Period, thus can retrieve freq
|
||||
tm.assert_index_equal(PeriodIndex(idx.values), idx)
|
||||
tm.assert_index_equal(PeriodIndex(list(idx.values)), idx)
|
||||
|
||||
msg = "freq not specified and cannot be inferred"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(idx.asi8)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(list(idx.asi8))
|
||||
|
||||
msg = "'Period' object is not iterable"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
PeriodIndex(data=Period("2007", freq="A"))
|
||||
|
||||
result = PeriodIndex(iter(idx))
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
result = PeriodIndex(idx)
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
result = PeriodIndex(idx, freq="M")
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
result = PeriodIndex(idx, freq=offsets.MonthEnd())
|
||||
tm.assert_index_equal(result, idx)
|
||||
assert result.freq == "M"
|
||||
|
||||
result = PeriodIndex(idx, freq="2M")
|
||||
tm.assert_index_equal(result, idx.asfreq("2M"))
|
||||
assert result.freq == "2M"
|
||||
|
||||
result = PeriodIndex(idx, freq=offsets.MonthEnd(2))
|
||||
tm.assert_index_equal(result, idx.asfreq("2M"))
|
||||
assert result.freq == "2M"
|
||||
|
||||
result = PeriodIndex(idx, freq="D")
|
||||
exp = idx.asfreq("D", "e")
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_constructor_datetime64arr(self):
|
||||
vals = np.arange(100000, 100000 + 10000, 100, dtype=np.int64)
|
||||
vals = vals.view(np.dtype("M8[us]"))
|
||||
|
||||
pi = PeriodIndex(vals, freq="D")
|
||||
|
||||
expected = PeriodIndex(vals.astype("M8[ns]"), freq="D")
|
||||
tm.assert_index_equal(pi, expected)
|
||||
|
||||
@pytest.mark.parametrize("box", [None, "series", "index"])
|
||||
def test_constructor_datetime64arr_ok(self, box):
|
||||
# https://github.com/pandas-dev/pandas/issues/23438
|
||||
data = date_range("2017", periods=4, freq="M")
|
||||
if box is None:
|
||||
data = data._values
|
||||
elif box == "series":
|
||||
data = Series(data)
|
||||
|
||||
result = PeriodIndex(data, freq="D")
|
||||
expected = PeriodIndex(
|
||||
["2017-01-31", "2017-02-28", "2017-03-31", "2017-04-30"], freq="D"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_constructor_dtype(self):
|
||||
# passing a dtype with a tz should localize
|
||||
idx = PeriodIndex(["2013-01", "2013-03"], dtype="period[M]")
|
||||
exp = PeriodIndex(["2013-01", "2013-03"], freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
assert idx.dtype == "period[M]"
|
||||
|
||||
idx = PeriodIndex(["2013-01-05", "2013-03-05"], dtype="period[3D]")
|
||||
exp = PeriodIndex(["2013-01-05", "2013-03-05"], freq="3D")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
assert idx.dtype == "period[3D]"
|
||||
|
||||
# if we already have a freq and its not the same, then asfreq
|
||||
# (not changed)
|
||||
idx = PeriodIndex(["2013-01-01", "2013-01-02"], freq="D")
|
||||
|
||||
res = PeriodIndex(idx, dtype="period[M]")
|
||||
exp = PeriodIndex(["2013-01", "2013-01"], freq="M")
|
||||
tm.assert_index_equal(res, exp)
|
||||
assert res.dtype == "period[M]"
|
||||
|
||||
res = PeriodIndex(idx, freq="M")
|
||||
tm.assert_index_equal(res, exp)
|
||||
assert res.dtype == "period[M]"
|
||||
|
||||
msg = "specified freq and dtype are different"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex(["2011-01"], freq="M", dtype="period[D]")
|
||||
|
||||
def test_constructor_empty(self):
|
||||
idx = PeriodIndex([], freq="M")
|
||||
assert isinstance(idx, PeriodIndex)
|
||||
assert len(idx) == 0
|
||||
assert idx.freq == "M"
|
||||
|
||||
with pytest.raises(ValueError, match="freq not specified"):
|
||||
PeriodIndex([])
|
||||
|
||||
def test_constructor_pi_nat(self):
|
||||
idx = PeriodIndex(
|
||||
[Period("2011-01", freq="M"), NaT, Period("2011-01", freq="M")]
|
||||
)
|
||||
exp = PeriodIndex(["2011-01", "NaT", "2011-01"], freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
idx = PeriodIndex(
|
||||
np.array([Period("2011-01", freq="M"), NaT, Period("2011-01", freq="M")])
|
||||
)
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
idx = PeriodIndex(
|
||||
[NaT, NaT, Period("2011-01", freq="M"), Period("2011-01", freq="M")]
|
||||
)
|
||||
exp = PeriodIndex(["NaT", "NaT", "2011-01", "2011-01"], freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
idx = PeriodIndex(
|
||||
np.array(
|
||||
[NaT, NaT, Period("2011-01", freq="M"), Period("2011-01", freq="M")]
|
||||
)
|
||||
)
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
idx = PeriodIndex([NaT, NaT, "2011-01", "2011-01"], freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
with pytest.raises(ValueError, match="freq not specified"):
|
||||
PeriodIndex([NaT, NaT])
|
||||
|
||||
with pytest.raises(ValueError, match="freq not specified"):
|
||||
PeriodIndex(np.array([NaT, NaT]))
|
||||
|
||||
with pytest.raises(ValueError, match="freq not specified"):
|
||||
PeriodIndex(["NaT", "NaT"])
|
||||
|
||||
with pytest.raises(ValueError, match="freq not specified"):
|
||||
PeriodIndex(np.array(["NaT", "NaT"]))
|
||||
|
||||
def test_constructor_incompat_freq(self):
|
||||
msg = "Input has different freq=D from PeriodIndex\\(freq=M\\)"
|
||||
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex([Period("2011-01", freq="M"), NaT, Period("2011-01", freq="D")])
|
||||
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex(
|
||||
np.array(
|
||||
[Period("2011-01", freq="M"), NaT, Period("2011-01", freq="D")]
|
||||
)
|
||||
)
|
||||
|
||||
# first element is NaT
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex([NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")])
|
||||
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex(
|
||||
np.array(
|
||||
[NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")]
|
||||
)
|
||||
)
|
||||
|
||||
def test_constructor_mixed(self):
|
||||
idx = PeriodIndex(["2011-01", NaT, Period("2011-01", freq="M")])
|
||||
exp = PeriodIndex(["2011-01", "NaT", "2011-01"], freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
idx = PeriodIndex(["NaT", NaT, Period("2011-01", freq="M")])
|
||||
exp = PeriodIndex(["NaT", "NaT", "2011-01"], freq="M")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
idx = PeriodIndex([Period("2011-01-01", freq="D"), NaT, "2012-01-01"])
|
||||
exp = PeriodIndex(["2011-01-01", "NaT", "2012-01-01"], freq="D")
|
||||
tm.assert_index_equal(idx, exp)
|
||||
|
||||
def test_constructor_simple_new(self):
|
||||
idx = period_range("2007-01", name="p", periods=2, freq="M")
|
||||
|
||||
with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"):
|
||||
idx._simple_new(idx, name="p")
|
||||
|
||||
result = idx._simple_new(idx._data, name="p")
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
msg = "Should be numpy array of type i8"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
# Need ndarray, not int64 Index
|
||||
type(idx._data)._simple_new(Index(idx.asi8), dtype=idx.dtype)
|
||||
|
||||
arr = type(idx._data)._simple_new(idx.asi8, dtype=idx.dtype)
|
||||
result = idx._simple_new(arr, name="p")
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
def test_constructor_simple_new_empty(self):
|
||||
# GH13079
|
||||
idx = PeriodIndex([], freq="M", name="p")
|
||||
with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"):
|
||||
idx._simple_new(idx, name="p")
|
||||
|
||||
result = idx._simple_new(idx._data, name="p")
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
@pytest.mark.parametrize("floats", [[1.1, 2.1], np.array([1.1, 2.1])])
|
||||
def test_constructor_floats(self, floats):
|
||||
with pytest.raises(AssertionError, match="<class "):
|
||||
PeriodIndex._simple_new(floats)
|
||||
|
||||
msg = "PeriodIndex does not allow floating point in construction"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
PeriodIndex(floats)
|
||||
|
||||
def test_constructor_nat(self):
|
||||
msg = "start and end must not be NaT"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="NaT", end="2011-01-01", freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2011-01-01", end="NaT", freq="M")
|
||||
|
||||
def test_constructor_year_and_quarter(self):
|
||||
year = Series([2001, 2002, 2003])
|
||||
quarter = year - 2000
|
||||
idx = PeriodIndex(year=year, quarter=quarter)
|
||||
strs = [f"{t[0]:d}Q{t[1]:d}" for t in zip(quarter, year)]
|
||||
lops = list(map(Period, strs))
|
||||
p = PeriodIndex(lops)
|
||||
tm.assert_index_equal(p, idx)
|
||||
|
||||
def test_constructor_freq_mult(self):
|
||||
# GH #7811
|
||||
pidx = period_range(start="2014-01", freq="2M", periods=4)
|
||||
expected = PeriodIndex(["2014-01", "2014-03", "2014-05", "2014-07"], freq="2M")
|
||||
tm.assert_index_equal(pidx, expected)
|
||||
|
||||
pidx = period_range(start="2014-01-02", end="2014-01-15", freq="3D")
|
||||
expected = PeriodIndex(
|
||||
["2014-01-02", "2014-01-05", "2014-01-08", "2014-01-11", "2014-01-14"],
|
||||
freq="3D",
|
||||
)
|
||||
tm.assert_index_equal(pidx, expected)
|
||||
|
||||
pidx = period_range(end="2014-01-01 17:00", freq="4H", periods=3)
|
||||
expected = PeriodIndex(
|
||||
["2014-01-01 09:00", "2014-01-01 13:00", "2014-01-01 17:00"], freq="4H"
|
||||
)
|
||||
tm.assert_index_equal(pidx, expected)
|
||||
|
||||
msg = "Frequency must be positive, because it represents span: -1M"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(["2011-01"], freq="-1M")
|
||||
|
||||
msg = "Frequency must be positive, because it represents span: 0M"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(["2011-01"], freq="0M")
|
||||
|
||||
msg = "Frequency must be positive, because it represents span: 0M"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range("2011-01", periods=3, freq="0M")
|
||||
|
||||
@pytest.mark.parametrize("freq", ["A", "M", "D", "T", "S"])
|
||||
@pytest.mark.parametrize("mult", [1, 2, 3, 4, 5])
|
||||
def test_constructor_freq_mult_dti_compat(self, mult, freq):
|
||||
freqstr = str(mult) + freq
|
||||
pidx = period_range(start="2014-04-01", freq=freqstr, periods=10)
|
||||
expected = date_range(start="2014-04-01", freq=freqstr, periods=10).to_period(
|
||||
freqstr
|
||||
)
|
||||
tm.assert_index_equal(pidx, expected)
|
||||
|
||||
def test_constructor_freq_combined(self):
|
||||
for freq in ["1D1H", "1H1D"]:
|
||||
pidx = PeriodIndex(["2016-01-01", "2016-01-02"], freq=freq)
|
||||
expected = PeriodIndex(["2016-01-01 00:00", "2016-01-02 00:00"], freq="25H")
|
||||
for freq in ["1D1H", "1H1D"]:
|
||||
pidx = period_range(start="2016-01-01", periods=2, freq=freq)
|
||||
expected = PeriodIndex(["2016-01-01 00:00", "2016-01-02 01:00"], freq="25H")
|
||||
tm.assert_index_equal(pidx, expected)
|
||||
|
||||
def test_constructor(self):
|
||||
pi = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
assert len(pi) == 9
|
||||
|
||||
pi = period_range(freq="Q", start="1/1/2001", end="12/1/2009")
|
||||
assert len(pi) == 4 * 9
|
||||
|
||||
pi = period_range(freq="M", start="1/1/2001", end="12/1/2009")
|
||||
assert len(pi) == 12 * 9
|
||||
|
||||
pi = period_range(freq="D", start="1/1/2001", end="12/31/2009")
|
||||
assert len(pi) == 365 * 9 + 2
|
||||
|
||||
msg = "Period with BDay freq is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
pi = period_range(freq="B", start="1/1/2001", end="12/31/2009")
|
||||
assert len(pi) == 261 * 9
|
||||
|
||||
pi = period_range(freq="H", start="1/1/2001", end="12/31/2001 23:00")
|
||||
assert len(pi) == 365 * 24
|
||||
|
||||
pi = period_range(freq="Min", start="1/1/2001", end="1/1/2001 23:59")
|
||||
assert len(pi) == 24 * 60
|
||||
|
||||
pi = period_range(freq="S", start="1/1/2001", end="1/1/2001 23:59:59")
|
||||
assert len(pi) == 24 * 60 * 60
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
start = Period("02-Apr-2005", "B")
|
||||
i1 = period_range(start=start, periods=20)
|
||||
assert len(i1) == 20
|
||||
assert i1.freq == start.freq
|
||||
assert i1[0] == start
|
||||
|
||||
end_intv = Period("2006-12-31", "W")
|
||||
i1 = period_range(end=end_intv, periods=10)
|
||||
assert len(i1) == 10
|
||||
assert i1.freq == end_intv.freq
|
||||
assert i1[-1] == end_intv
|
||||
|
||||
end_intv = Period("2006-12-31", "1w")
|
||||
i2 = period_range(end=end_intv, periods=10)
|
||||
assert len(i1) == len(i2)
|
||||
assert (i1 == i2).all()
|
||||
assert i1.freq == i2.freq
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
end_intv = Period("2005-05-01", "B")
|
||||
i1 = period_range(start=start, end=end_intv)
|
||||
|
||||
# infer freq from first element
|
||||
i2 = PeriodIndex([end_intv, Period("2005-05-05", "B")])
|
||||
assert len(i2) == 2
|
||||
assert i2[0] == end_intv
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
i2 = PeriodIndex(np.array([end_intv, Period("2005-05-05", "B")]))
|
||||
assert len(i2) == 2
|
||||
assert i2[0] == end_intv
|
||||
|
||||
# Mixed freq should fail
|
||||
vals = [end_intv, Period("2006-12-31", "w")]
|
||||
msg = r"Input has different freq=W-SUN from PeriodIndex\(freq=B\)"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex(vals)
|
||||
vals = np.array(vals)
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex(vals)
|
||||
|
||||
# tuple freq disallowed GH#34703
|
||||
with pytest.raises(TypeError, match="pass as a string instead"):
|
||||
Period("2006-12-31", ("w", 1))
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq", ["M", "Q", "A", "D", "B", "T", "S", "L", "U", "N", "H"]
|
||||
)
|
||||
@pytest.mark.filterwarnings(
|
||||
r"ignore:Period with BDay freq is deprecated:FutureWarning"
|
||||
)
|
||||
@pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning")
|
||||
def test_recreate_from_data(self, freq):
|
||||
org = period_range(start="2001/04/01", freq=freq, periods=1)
|
||||
idx = PeriodIndex(org.values, freq=freq)
|
||||
tm.assert_index_equal(idx, org)
|
||||
|
||||
def test_map_with_string_constructor(self):
|
||||
raw = [2005, 2007, 2009]
|
||||
index = PeriodIndex(raw, freq="A")
|
||||
|
||||
expected = Index([str(num) for num in raw])
|
||||
res = index.map(str)
|
||||
|
||||
# should return an Index
|
||||
assert isinstance(res, Index)
|
||||
|
||||
# preserve element types
|
||||
assert all(isinstance(resi, str) for resi in res)
|
||||
|
||||
# lastly, values should compare equal
|
||||
tm.assert_index_equal(res, expected)
|
||||
|
||||
|
||||
class TestShallowCopy:
|
||||
def test_shallow_copy_empty(self):
|
||||
# GH#13067
|
||||
idx = PeriodIndex([], freq="M")
|
||||
result = idx._view()
|
||||
expected = idx
|
||||
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_shallow_copy_disallow_i8(self):
|
||||
# GH#24391
|
||||
pi = period_range("2018-01-01", periods=3, freq="2D")
|
||||
with pytest.raises(AssertionError, match="ndarray"):
|
||||
pi._shallow_copy(pi.asi8)
|
||||
|
||||
def test_shallow_copy_requires_disallow_period_index(self):
|
||||
pi = period_range("2018-01-01", periods=3, freq="2D")
|
||||
with pytest.raises(AssertionError, match="PeriodIndex"):
|
||||
pi._shallow_copy(pi)
|
||||
|
||||
|
||||
class TestSeriesPeriod:
|
||||
def test_constructor_cant_cast_period(self):
|
||||
msg = "Cannot cast PeriodIndex to dtype float64"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
Series(period_range("2000-01-01", periods=10, freq="D"), dtype=float)
|
||||
|
||||
def test_constructor_cast_object(self):
|
||||
s = Series(period_range("1/1/2000", periods=10), dtype=PeriodDtype("D"))
|
||||
exp = Series(period_range("1/1/2000", periods=10))
|
||||
tm.assert_series_equal(s, exp)
|
@@ -0,0 +1,199 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
Series,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def test_to_native_types():
|
||||
index = PeriodIndex(["2017-01-01", "2017-01-02", "2017-01-03"], freq="D")
|
||||
|
||||
# First, with no arguments.
|
||||
expected = np.array(["2017-01-01", "2017-01-02", "2017-01-03"], dtype=object)
|
||||
|
||||
result = index._format_native_types()
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# No NaN values, so na_rep has no effect
|
||||
result = index._format_native_types(na_rep="pandas")
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# Make sure date formatting works
|
||||
expected = np.array(["01-2017-01", "01-2017-02", "01-2017-03"], dtype=object)
|
||||
|
||||
result = index._format_native_types(date_format="%m-%Y-%d")
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# NULL object handling should work
|
||||
index = PeriodIndex(["2017-01-01", pd.NaT, "2017-01-03"], freq="D")
|
||||
expected = np.array(["2017-01-01", "NaT", "2017-01-03"], dtype=object)
|
||||
|
||||
result = index._format_native_types()
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
expected = np.array(["2017-01-01", "pandas", "2017-01-03"], dtype=object)
|
||||
|
||||
result = index._format_native_types(na_rep="pandas")
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
|
||||
class TestPeriodIndexRendering:
|
||||
def test_frame_repr(self):
|
||||
df = pd.DataFrame({"A": [1, 2, 3]}, index=pd.date_range("2000", periods=3))
|
||||
result = repr(df)
|
||||
expected = " A\n2000-01-01 1\n2000-01-02 2\n2000-01-03 3"
|
||||
assert result == expected
|
||||
|
||||
@pytest.mark.parametrize("method", ["__repr__", "__str__"])
|
||||
def test_representation(self, method):
|
||||
# GH#7601
|
||||
idx1 = PeriodIndex([], freq="D")
|
||||
idx2 = PeriodIndex(["2011-01-01"], freq="D")
|
||||
idx3 = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D")
|
||||
idx4 = PeriodIndex(["2011-01-01", "2011-01-02", "2011-01-03"], freq="D")
|
||||
idx5 = PeriodIndex(["2011", "2012", "2013"], freq="A")
|
||||
idx6 = PeriodIndex(["2011-01-01 09:00", "2012-02-01 10:00", "NaT"], freq="H")
|
||||
idx7 = pd.period_range("2013Q1", periods=1, freq="Q")
|
||||
idx8 = pd.period_range("2013Q1", periods=2, freq="Q")
|
||||
idx9 = pd.period_range("2013Q1", periods=3, freq="Q")
|
||||
idx10 = PeriodIndex(["2011-01-01", "2011-02-01"], freq="3D")
|
||||
|
||||
exp1 = "PeriodIndex([], dtype='period[D]')"
|
||||
|
||||
exp2 = "PeriodIndex(['2011-01-01'], dtype='period[D]')"
|
||||
|
||||
exp3 = "PeriodIndex(['2011-01-01', '2011-01-02'], dtype='period[D]')"
|
||||
|
||||
exp4 = (
|
||||
"PeriodIndex(['2011-01-01', '2011-01-02', '2011-01-03'], "
|
||||
"dtype='period[D]')"
|
||||
)
|
||||
|
||||
exp5 = "PeriodIndex(['2011', '2012', '2013'], dtype='period[A-DEC]')"
|
||||
|
||||
exp6 = (
|
||||
"PeriodIndex(['2011-01-01 09:00', '2012-02-01 10:00', 'NaT'], "
|
||||
"dtype='period[H]')"
|
||||
)
|
||||
|
||||
exp7 = "PeriodIndex(['2013Q1'], dtype='period[Q-DEC]')"
|
||||
|
||||
exp8 = "PeriodIndex(['2013Q1', '2013Q2'], dtype='period[Q-DEC]')"
|
||||
|
||||
exp9 = "PeriodIndex(['2013Q1', '2013Q2', '2013Q3'], dtype='period[Q-DEC]')"
|
||||
|
||||
exp10 = "PeriodIndex(['2011-01-01', '2011-02-01'], dtype='period[3D]')"
|
||||
|
||||
for idx, expected in zip(
|
||||
[idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9, idx10],
|
||||
[exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, exp9, exp10],
|
||||
):
|
||||
result = getattr(idx, method)()
|
||||
assert result == expected
|
||||
|
||||
def test_representation_to_series(self):
|
||||
# GH#10971
|
||||
idx1 = PeriodIndex([], freq="D")
|
||||
idx2 = PeriodIndex(["2011-01-01"], freq="D")
|
||||
idx3 = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D")
|
||||
idx4 = PeriodIndex(["2011-01-01", "2011-01-02", "2011-01-03"], freq="D")
|
||||
idx5 = PeriodIndex(["2011", "2012", "2013"], freq="A")
|
||||
idx6 = PeriodIndex(["2011-01-01 09:00", "2012-02-01 10:00", "NaT"], freq="H")
|
||||
|
||||
idx7 = pd.period_range("2013Q1", periods=1, freq="Q")
|
||||
idx8 = pd.period_range("2013Q1", periods=2, freq="Q")
|
||||
idx9 = pd.period_range("2013Q1", periods=3, freq="Q")
|
||||
|
||||
exp1 = """Series([], dtype: period[D])"""
|
||||
|
||||
exp2 = """0 2011-01-01
|
||||
dtype: period[D]"""
|
||||
|
||||
exp3 = """0 2011-01-01
|
||||
1 2011-01-02
|
||||
dtype: period[D]"""
|
||||
|
||||
exp4 = """0 2011-01-01
|
||||
1 2011-01-02
|
||||
2 2011-01-03
|
||||
dtype: period[D]"""
|
||||
|
||||
exp5 = """0 2011
|
||||
1 2012
|
||||
2 2013
|
||||
dtype: period[A-DEC]"""
|
||||
|
||||
exp6 = """0 2011-01-01 09:00
|
||||
1 2012-02-01 10:00
|
||||
2 NaT
|
||||
dtype: period[H]"""
|
||||
|
||||
exp7 = """0 2013Q1
|
||||
dtype: period[Q-DEC]"""
|
||||
|
||||
exp8 = """0 2013Q1
|
||||
1 2013Q2
|
||||
dtype: period[Q-DEC]"""
|
||||
|
||||
exp9 = """0 2013Q1
|
||||
1 2013Q2
|
||||
2 2013Q3
|
||||
dtype: period[Q-DEC]"""
|
||||
|
||||
for idx, expected in zip(
|
||||
[idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9],
|
||||
[exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, exp9],
|
||||
):
|
||||
result = repr(Series(idx))
|
||||
assert result == expected
|
||||
|
||||
def test_summary(self):
|
||||
# GH#9116
|
||||
idx1 = PeriodIndex([], freq="D")
|
||||
idx2 = PeriodIndex(["2011-01-01"], freq="D")
|
||||
idx3 = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D")
|
||||
idx4 = PeriodIndex(["2011-01-01", "2011-01-02", "2011-01-03"], freq="D")
|
||||
idx5 = PeriodIndex(["2011", "2012", "2013"], freq="A")
|
||||
idx6 = PeriodIndex(["2011-01-01 09:00", "2012-02-01 10:00", "NaT"], freq="H")
|
||||
|
||||
idx7 = pd.period_range("2013Q1", periods=1, freq="Q")
|
||||
idx8 = pd.period_range("2013Q1", periods=2, freq="Q")
|
||||
idx9 = pd.period_range("2013Q1", periods=3, freq="Q")
|
||||
|
||||
exp1 = """PeriodIndex: 0 entries
|
||||
Freq: D"""
|
||||
|
||||
exp2 = """PeriodIndex: 1 entries, 2011-01-01 to 2011-01-01
|
||||
Freq: D"""
|
||||
|
||||
exp3 = """PeriodIndex: 2 entries, 2011-01-01 to 2011-01-02
|
||||
Freq: D"""
|
||||
|
||||
exp4 = """PeriodIndex: 3 entries, 2011-01-01 to 2011-01-03
|
||||
Freq: D"""
|
||||
|
||||
exp5 = """PeriodIndex: 3 entries, 2011 to 2013
|
||||
Freq: A-DEC"""
|
||||
|
||||
exp6 = """PeriodIndex: 3 entries, 2011-01-01 09:00 to NaT
|
||||
Freq: H"""
|
||||
|
||||
exp7 = """PeriodIndex: 1 entries, 2013Q1 to 2013Q1
|
||||
Freq: Q-DEC"""
|
||||
|
||||
exp8 = """PeriodIndex: 2 entries, 2013Q1 to 2013Q2
|
||||
Freq: Q-DEC"""
|
||||
|
||||
exp9 = """PeriodIndex: 3 entries, 2013Q1 to 2013Q3
|
||||
Freq: Q-DEC"""
|
||||
|
||||
for idx, expected in zip(
|
||||
[idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9],
|
||||
[exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, exp9],
|
||||
):
|
||||
result = idx._summary()
|
||||
assert result == expected
|
@@ -0,0 +1,28 @@
|
||||
import pytest
|
||||
|
||||
from pandas.compat import PY311
|
||||
|
||||
from pandas import (
|
||||
offsets,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestFreq:
|
||||
def test_freq_setter_deprecated(self):
|
||||
# GH#20678
|
||||
idx = period_range("2018Q1", periods=4, freq="Q")
|
||||
|
||||
# no warning for getter
|
||||
with tm.assert_produces_warning(None):
|
||||
idx.freq
|
||||
|
||||
# warning for setter
|
||||
msg = (
|
||||
"property 'freq' of 'PeriodArray' object has no setter"
|
||||
if PY311
|
||||
else "can't set attribute"
|
||||
)
|
||||
with pytest.raises(AttributeError, match=msg):
|
||||
idx.freq = offsets.Day()
|
@@ -0,0 +1,815 @@
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import period as libperiod
|
||||
from pandas.errors import InvalidIndexError
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
DatetimeIndex,
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
Series,
|
||||
Timedelta,
|
||||
date_range,
|
||||
notna,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
dti4 = date_range("2016-01-01", periods=4)
|
||||
dti = dti4[:-1]
|
||||
rng = pd.Index(range(3))
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=[
|
||||
dti,
|
||||
dti.tz_localize("UTC"),
|
||||
dti.to_period("W"),
|
||||
dti - dti[0],
|
||||
rng,
|
||||
pd.Index([1, 2, 3]),
|
||||
pd.Index([2.0, 3.0, 4.0]),
|
||||
pd.Index([4, 5, 6], dtype="u8"),
|
||||
pd.IntervalIndex.from_breaks(dti4),
|
||||
]
|
||||
)
|
||||
def non_comparable_idx(request):
|
||||
# All have length 3
|
||||
return request.param
|
||||
|
||||
|
||||
class TestGetItem:
|
||||
def test_getitem_slice_keeps_name(self):
|
||||
idx = period_range("20010101", periods=10, freq="D", name="bob")
|
||||
assert idx.name == idx[1:].name
|
||||
|
||||
def test_getitem(self):
|
||||
idx1 = period_range("2011-01-01", "2011-01-31", freq="D", name="idx")
|
||||
|
||||
for idx in [idx1]:
|
||||
result = idx[0]
|
||||
assert result == Period("2011-01-01", freq="D")
|
||||
|
||||
result = idx[-1]
|
||||
assert result == Period("2011-01-31", freq="D")
|
||||
|
||||
result = idx[0:5]
|
||||
expected = period_range("2011-01-01", "2011-01-05", freq="D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
result = idx[0:10:2]
|
||||
expected = PeriodIndex(
|
||||
["2011-01-01", "2011-01-03", "2011-01-05", "2011-01-07", "2011-01-09"],
|
||||
freq="D",
|
||||
name="idx",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
result = idx[-20:-5:3]
|
||||
expected = PeriodIndex(
|
||||
["2011-01-12", "2011-01-15", "2011-01-18", "2011-01-21", "2011-01-24"],
|
||||
freq="D",
|
||||
name="idx",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
result = idx[4::-1]
|
||||
expected = PeriodIndex(
|
||||
["2011-01-05", "2011-01-04", "2011-01-03", "2011-01-02", "2011-01-01"],
|
||||
freq="D",
|
||||
name="idx",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
def test_getitem_index(self):
|
||||
idx = period_range("2007-01", periods=10, freq="M", name="x")
|
||||
|
||||
result = idx[[1, 3, 5]]
|
||||
exp = PeriodIndex(["2007-02", "2007-04", "2007-06"], freq="M", name="x")
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
result = idx[[True, True, False, False, False, True, True, False, False, False]]
|
||||
exp = PeriodIndex(
|
||||
["2007-01", "2007-02", "2007-06", "2007-07"], freq="M", name="x"
|
||||
)
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_getitem_partial(self):
|
||||
rng = period_range("2007-01", periods=50, freq="M")
|
||||
ts = Series(np.random.default_rng(2).standard_normal(len(rng)), rng)
|
||||
|
||||
with pytest.raises(KeyError, match=r"^'2006'$"):
|
||||
ts["2006"]
|
||||
|
||||
result = ts["2008"]
|
||||
assert (result.index.year == 2008).all()
|
||||
|
||||
result = ts["2008":"2009"]
|
||||
assert len(result) == 24
|
||||
|
||||
result = ts["2008-1":"2009-12"]
|
||||
assert len(result) == 24
|
||||
|
||||
result = ts["2008Q1":"2009Q4"]
|
||||
assert len(result) == 24
|
||||
|
||||
result = ts[:"2009"]
|
||||
assert len(result) == 36
|
||||
|
||||
result = ts["2009":]
|
||||
assert len(result) == 50 - 24
|
||||
|
||||
exp = result
|
||||
result = ts[24:]
|
||||
tm.assert_series_equal(exp, result)
|
||||
|
||||
ts = pd.concat([ts[10:], ts[10:]])
|
||||
msg = "left slice bound for non-unique label: '2008'"
|
||||
with pytest.raises(KeyError, match=msg):
|
||||
ts[slice("2008", "2009")]
|
||||
|
||||
def test_getitem_datetime(self):
|
||||
rng = period_range(start="2012-01-01", periods=10, freq="W-MON")
|
||||
ts = Series(range(len(rng)), index=rng)
|
||||
|
||||
dt1 = datetime(2011, 10, 2)
|
||||
dt4 = datetime(2012, 4, 20)
|
||||
|
||||
rs = ts[dt1:dt4]
|
||||
tm.assert_series_equal(rs, ts)
|
||||
|
||||
def test_getitem_nat(self):
|
||||
idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="M")
|
||||
assert idx[0] == Period("2011-01", freq="M")
|
||||
assert idx[1] is NaT
|
||||
|
||||
s = Series([0, 1, 2], index=idx)
|
||||
assert s[NaT] == 1
|
||||
|
||||
s = Series(idx, index=idx)
|
||||
assert s[Period("2011-01", freq="M")] == Period("2011-01", freq="M")
|
||||
assert s[NaT] is NaT
|
||||
|
||||
def test_getitem_list_periods(self):
|
||||
# GH 7710
|
||||
rng = period_range(start="2012-01-01", periods=10, freq="D")
|
||||
ts = Series(range(len(rng)), index=rng)
|
||||
exp = ts.iloc[[1]]
|
||||
tm.assert_series_equal(ts[[Period("2012-01-02", freq="D")]], exp)
|
||||
|
||||
@pytest.mark.arm_slow
|
||||
def test_getitem_seconds(self):
|
||||
# GH#6716
|
||||
didx = date_range(start="2013/01/01 09:00:00", freq="S", periods=4000)
|
||||
pidx = period_range(start="2013/01/01 09:00:00", freq="S", periods=4000)
|
||||
|
||||
for idx in [didx, pidx]:
|
||||
# getitem against index should raise ValueError
|
||||
values = [
|
||||
"2014",
|
||||
"2013/02",
|
||||
"2013/01/02",
|
||||
"2013/02/01 9H",
|
||||
"2013/02/01 09:00",
|
||||
]
|
||||
for val in values:
|
||||
# GH7116
|
||||
# these show deprecations as we are trying
|
||||
# to slice with non-integer indexers
|
||||
with pytest.raises(IndexError, match="only integers, slices"):
|
||||
idx[val]
|
||||
|
||||
ser = Series(np.random.default_rng(2).random(len(idx)), index=idx)
|
||||
tm.assert_series_equal(ser["2013/01/01 10:00"], ser[3600:3660])
|
||||
tm.assert_series_equal(ser["2013/01/01 9H"], ser[:3600])
|
||||
for d in ["2013/01/01", "2013/01", "2013"]:
|
||||
tm.assert_series_equal(ser[d], ser)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"idx_range",
|
||||
[
|
||||
date_range,
|
||||
period_range,
|
||||
],
|
||||
)
|
||||
def test_getitem_day(self, idx_range):
|
||||
# GH#6716
|
||||
# Confirm DatetimeIndex and PeriodIndex works identically
|
||||
# getitem against index should raise ValueError
|
||||
idx = idx_range(start="2013/01/01", freq="D", periods=400)
|
||||
values = [
|
||||
"2014",
|
||||
"2013/02",
|
||||
"2013/01/02",
|
||||
"2013/02/01 9H",
|
||||
"2013/02/01 09:00",
|
||||
]
|
||||
for val in values:
|
||||
# GH7116
|
||||
# these show deprecations as we are trying
|
||||
# to slice with non-integer indexers
|
||||
with pytest.raises(IndexError, match="only integers, slices"):
|
||||
idx[val]
|
||||
|
||||
ser = Series(np.random.default_rng(2).random(len(idx)), index=idx)
|
||||
tm.assert_series_equal(ser["2013/01"], ser[0:31])
|
||||
tm.assert_series_equal(ser["2013/02"], ser[31:59])
|
||||
tm.assert_series_equal(ser["2014"], ser[365:])
|
||||
|
||||
invalid = ["2013/02/01 9H", "2013/02/01 09:00"]
|
||||
for val in invalid:
|
||||
with pytest.raises(KeyError, match=val):
|
||||
ser[val]
|
||||
|
||||
|
||||
class TestGetLoc:
|
||||
def test_get_loc_msg(self):
|
||||
idx = period_range("2000-1-1", freq="A", periods=10)
|
||||
bad_period = Period("2012", "A")
|
||||
with pytest.raises(KeyError, match=r"^Period\('2012', 'A-DEC'\)$"):
|
||||
idx.get_loc(bad_period)
|
||||
|
||||
try:
|
||||
idx.get_loc(bad_period)
|
||||
except KeyError as inst:
|
||||
assert inst.args[0] == bad_period
|
||||
|
||||
def test_get_loc_nat(self):
|
||||
didx = DatetimeIndex(["2011-01-01", "NaT", "2011-01-03"])
|
||||
pidx = PeriodIndex(["2011-01-01", "NaT", "2011-01-03"], freq="M")
|
||||
|
||||
# check DatetimeIndex compat
|
||||
for idx in [didx, pidx]:
|
||||
assert idx.get_loc(NaT) == 1
|
||||
assert idx.get_loc(None) == 1
|
||||
assert idx.get_loc(float("nan")) == 1
|
||||
assert idx.get_loc(np.nan) == 1
|
||||
|
||||
def test_get_loc(self):
|
||||
# GH 17717
|
||||
p0 = Period("2017-09-01")
|
||||
p1 = Period("2017-09-02")
|
||||
p2 = Period("2017-09-03")
|
||||
|
||||
# get the location of p1/p2 from
|
||||
# monotonic increasing PeriodIndex with non-duplicate
|
||||
idx0 = PeriodIndex([p0, p1, p2])
|
||||
expected_idx1_p1 = 1
|
||||
expected_idx1_p2 = 2
|
||||
|
||||
assert idx0.get_loc(p1) == expected_idx1_p1
|
||||
assert idx0.get_loc(str(p1)) == expected_idx1_p1
|
||||
assert idx0.get_loc(p2) == expected_idx1_p2
|
||||
assert idx0.get_loc(str(p2)) == expected_idx1_p2
|
||||
|
||||
msg = "Cannot interpret 'foo' as period"
|
||||
with pytest.raises(KeyError, match=msg):
|
||||
idx0.get_loc("foo")
|
||||
with pytest.raises(KeyError, match=r"^1\.1$"):
|
||||
idx0.get_loc(1.1)
|
||||
|
||||
with pytest.raises(InvalidIndexError, match=re.escape(str(idx0))):
|
||||
idx0.get_loc(idx0)
|
||||
|
||||
# get the location of p1/p2 from
|
||||
# monotonic increasing PeriodIndex with duplicate
|
||||
idx1 = PeriodIndex([p1, p1, p2])
|
||||
expected_idx1_p1 = slice(0, 2)
|
||||
expected_idx1_p2 = 2
|
||||
|
||||
assert idx1.get_loc(p1) == expected_idx1_p1
|
||||
assert idx1.get_loc(str(p1)) == expected_idx1_p1
|
||||
assert idx1.get_loc(p2) == expected_idx1_p2
|
||||
assert idx1.get_loc(str(p2)) == expected_idx1_p2
|
||||
|
||||
msg = "Cannot interpret 'foo' as period"
|
||||
with pytest.raises(KeyError, match=msg):
|
||||
idx1.get_loc("foo")
|
||||
|
||||
with pytest.raises(KeyError, match=r"^1\.1$"):
|
||||
idx1.get_loc(1.1)
|
||||
|
||||
with pytest.raises(InvalidIndexError, match=re.escape(str(idx1))):
|
||||
idx1.get_loc(idx1)
|
||||
|
||||
# get the location of p1/p2 from
|
||||
# non-monotonic increasing/decreasing PeriodIndex with duplicate
|
||||
idx2 = PeriodIndex([p2, p1, p2])
|
||||
expected_idx2_p1 = 1
|
||||
expected_idx2_p2 = np.array([True, False, True])
|
||||
|
||||
assert idx2.get_loc(p1) == expected_idx2_p1
|
||||
assert idx2.get_loc(str(p1)) == expected_idx2_p1
|
||||
tm.assert_numpy_array_equal(idx2.get_loc(p2), expected_idx2_p2)
|
||||
tm.assert_numpy_array_equal(idx2.get_loc(str(p2)), expected_idx2_p2)
|
||||
|
||||
def test_get_loc_integer(self):
|
||||
dti = date_range("2016-01-01", periods=3)
|
||||
pi = dti.to_period("D")
|
||||
with pytest.raises(KeyError, match="16801"):
|
||||
pi.get_loc(16801)
|
||||
|
||||
pi2 = dti.to_period("Y") # duplicates, ordinals are all 46
|
||||
with pytest.raises(KeyError, match="46"):
|
||||
pi2.get_loc(46)
|
||||
|
||||
def test_get_loc_invalid_string_raises_keyerror(self):
|
||||
# GH#34240
|
||||
pi = period_range("2000", periods=3, name="A")
|
||||
with pytest.raises(KeyError, match="A"):
|
||||
pi.get_loc("A")
|
||||
|
||||
ser = Series([1, 2, 3], index=pi)
|
||||
with pytest.raises(KeyError, match="A"):
|
||||
ser.loc["A"]
|
||||
|
||||
with pytest.raises(KeyError, match="A"):
|
||||
ser["A"]
|
||||
|
||||
assert "A" not in ser
|
||||
assert "A" not in pi
|
||||
|
||||
def test_get_loc_mismatched_freq(self):
|
||||
# see also test_get_indexer_mismatched_dtype testing we get analogous
|
||||
# behavior for get_loc
|
||||
dti = date_range("2016-01-01", periods=3)
|
||||
pi = dti.to_period("D")
|
||||
pi2 = dti.to_period("W")
|
||||
pi3 = pi.view(pi2.dtype) # i.e. matching i8 representations
|
||||
|
||||
with pytest.raises(KeyError, match="W-SUN"):
|
||||
pi.get_loc(pi2[0])
|
||||
|
||||
with pytest.raises(KeyError, match="W-SUN"):
|
||||
# even though we have matching i8 values
|
||||
pi.get_loc(pi3[0])
|
||||
|
||||
|
||||
class TestGetIndexer:
|
||||
def test_get_indexer(self):
|
||||
# GH 17717
|
||||
p1 = Period("2017-09-01")
|
||||
p2 = Period("2017-09-04")
|
||||
p3 = Period("2017-09-07")
|
||||
|
||||
tp0 = Period("2017-08-31")
|
||||
tp1 = Period("2017-09-02")
|
||||
tp2 = Period("2017-09-05")
|
||||
tp3 = Period("2017-09-09")
|
||||
|
||||
idx = PeriodIndex([p1, p2, p3])
|
||||
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
|
||||
target = PeriodIndex([tp0, tp1, tp2, tp3])
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "pad"), np.array([-1, 0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "backfill"), np.array([0, 1, 2, -1], dtype=np.intp)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "nearest"), np.array([0, 0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
|
||||
res = idx.get_indexer(target, "nearest", tolerance=Timedelta("1 day"))
|
||||
tm.assert_numpy_array_equal(res, np.array([0, 0, 1, -1], dtype=np.intp))
|
||||
|
||||
def test_get_indexer_mismatched_dtype(self):
|
||||
# Check that we return all -1s and do not raise or cast incorrectly
|
||||
|
||||
dti = date_range("2016-01-01", periods=3)
|
||||
pi = dti.to_period("D")
|
||||
pi2 = dti.to_period("W")
|
||||
|
||||
expected = np.array([-1, -1, -1], dtype=np.intp)
|
||||
|
||||
result = pi.get_indexer(dti)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# This should work in both directions
|
||||
result = dti.get_indexer(pi)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
result = pi.get_indexer(pi2)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# We expect the same from get_indexer_non_unique
|
||||
result = pi.get_indexer_non_unique(dti)[0]
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
result = dti.get_indexer_non_unique(pi)[0]
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
result = pi.get_indexer_non_unique(pi2)[0]
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
def test_get_indexer_mismatched_dtype_different_length(self, non_comparable_idx):
|
||||
# without method we aren't checking inequalities, so get all-missing
|
||||
# but do not raise
|
||||
dti = date_range("2016-01-01", periods=3)
|
||||
pi = dti.to_period("D")
|
||||
|
||||
other = non_comparable_idx
|
||||
|
||||
res = pi[:-1].get_indexer(other)
|
||||
expected = -np.ones(other.shape, dtype=np.intp)
|
||||
tm.assert_numpy_array_equal(res, expected)
|
||||
|
||||
@pytest.mark.parametrize("method", ["pad", "backfill", "nearest"])
|
||||
def test_get_indexer_mismatched_dtype_with_method(self, non_comparable_idx, method):
|
||||
dti = date_range("2016-01-01", periods=3)
|
||||
pi = dti.to_period("D")
|
||||
|
||||
other = non_comparable_idx
|
||||
|
||||
msg = re.escape(f"Cannot compare dtypes {pi.dtype} and {other.dtype}")
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pi.get_indexer(other, method=method)
|
||||
|
||||
for dtype in ["object", "category"]:
|
||||
other2 = other.astype(dtype)
|
||||
if dtype == "object" and isinstance(other, PeriodIndex):
|
||||
continue
|
||||
# Two different error message patterns depending on dtypes
|
||||
msg = "|".join(
|
||||
[
|
||||
re.escape(msg)
|
||||
for msg in (
|
||||
f"Cannot compare dtypes {pi.dtype} and {other.dtype}",
|
||||
" not supported between instances of ",
|
||||
)
|
||||
]
|
||||
)
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pi.get_indexer(other2, method=method)
|
||||
|
||||
def test_get_indexer_non_unique(self):
|
||||
# GH 17717
|
||||
p1 = Period("2017-09-02")
|
||||
p2 = Period("2017-09-03")
|
||||
p3 = Period("2017-09-04")
|
||||
p4 = Period("2017-09-05")
|
||||
|
||||
idx1 = PeriodIndex([p1, p2, p1])
|
||||
idx2 = PeriodIndex([p2, p1, p3, p4])
|
||||
|
||||
result = idx1.get_indexer_non_unique(idx2)
|
||||
expected_indexer = np.array([1, 0, 2, -1, -1], dtype=np.intp)
|
||||
expected_missing = np.array([2, 3], dtype=np.intp)
|
||||
|
||||
tm.assert_numpy_array_equal(result[0], expected_indexer)
|
||||
tm.assert_numpy_array_equal(result[1], expected_missing)
|
||||
|
||||
# TODO: This method came from test_period; de-dup with version above
|
||||
def test_get_indexer2(self):
|
||||
idx = period_range("2000-01-01", periods=3).asfreq("H", how="start")
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp)
|
||||
)
|
||||
|
||||
target = PeriodIndex(
|
||||
["1999-12-31T23", "2000-01-01T12", "2000-01-02T01"], freq="H"
|
||||
)
|
||||
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)
|
||||
)
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "nearest", tolerance="1 hour"),
|
||||
np.array([0, -1, 1], dtype=np.intp),
|
||||
)
|
||||
|
||||
msg = "Input has different freq=None from PeriodArray\\(freq=H\\)"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
idx.get_indexer(target, "nearest", tolerance="1 minute")
|
||||
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(target, "nearest", tolerance="1 day"),
|
||||
np.array([0, 1, 1], dtype=np.intp),
|
||||
)
|
||||
tol_raw = [
|
||||
Timedelta("1 hour"),
|
||||
Timedelta("1 hour"),
|
||||
np.timedelta64(1, "D"),
|
||||
]
|
||||
tm.assert_numpy_array_equal(
|
||||
idx.get_indexer(
|
||||
target, "nearest", tolerance=[np.timedelta64(x) for x in tol_raw]
|
||||
),
|
||||
np.array([0, -1, 1], dtype=np.intp),
|
||||
)
|
||||
tol_bad = [
|
||||
Timedelta("2 hour").to_timedelta64(),
|
||||
Timedelta("1 hour").to_timedelta64(),
|
||||
np.timedelta64(1, "M"),
|
||||
]
|
||||
with pytest.raises(
|
||||
libperiod.IncompatibleFrequency, match="Input has different freq=None from"
|
||||
):
|
||||
idx.get_indexer(target, "nearest", tolerance=tol_bad)
|
||||
|
||||
|
||||
class TestWhere:
|
||||
def test_where(self, listlike_box):
|
||||
i = period_range("20130101", periods=5, freq="D")
|
||||
cond = [True] * len(i)
|
||||
expected = i
|
||||
result = i.where(listlike_box(cond))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
cond = [False] + [True] * (len(i) - 1)
|
||||
expected = PeriodIndex([NaT] + i[1:].tolist(), freq="D")
|
||||
result = i.where(listlike_box(cond))
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_where_other(self):
|
||||
i = period_range("20130101", periods=5, freq="D")
|
||||
for arr in [np.nan, NaT]:
|
||||
result = i.where(notna(i), other=arr)
|
||||
expected = i
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
i2 = i.copy()
|
||||
i2 = PeriodIndex([NaT, NaT] + i[2:].tolist(), freq="D")
|
||||
result = i.where(notna(i2), i2)
|
||||
tm.assert_index_equal(result, i2)
|
||||
|
||||
i2 = i.copy()
|
||||
i2 = PeriodIndex([NaT, NaT] + i[2:].tolist(), freq="D")
|
||||
result = i.where(notna(i2), i2.values)
|
||||
tm.assert_index_equal(result, i2)
|
||||
|
||||
def test_where_invalid_dtypes(self):
|
||||
pi = period_range("20130101", periods=5, freq="D")
|
||||
|
||||
tail = pi[2:].tolist()
|
||||
i2 = PeriodIndex([NaT, NaT] + tail, freq="D")
|
||||
mask = notna(i2)
|
||||
|
||||
result = pi.where(mask, i2.asi8)
|
||||
expected = pd.Index([NaT._value, NaT._value] + tail, dtype=object)
|
||||
assert isinstance(expected[0], int)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
tdi = i2.asi8.view("timedelta64[ns]")
|
||||
expected = pd.Index([tdi[0], tdi[1]] + tail, dtype=object)
|
||||
assert isinstance(expected[0], np.timedelta64)
|
||||
result = pi.where(mask, tdi)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
dti = i2.to_timestamp("S")
|
||||
expected = pd.Index([dti[0], dti[1]] + tail, dtype=object)
|
||||
assert expected[0] is NaT
|
||||
result = pi.where(mask, dti)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
td = Timedelta(days=4)
|
||||
expected = pd.Index([td, td] + tail, dtype=object)
|
||||
assert expected[0] == td
|
||||
result = pi.where(mask, td)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_where_mismatched_nat(self):
|
||||
pi = period_range("20130101", periods=5, freq="D")
|
||||
cond = np.array([True, False, True, True, False])
|
||||
|
||||
tdnat = np.timedelta64("NaT", "ns")
|
||||
expected = pd.Index([pi[0], tdnat, pi[2], pi[3], tdnat], dtype=object)
|
||||
assert expected[1] is tdnat
|
||||
result = pi.where(cond, tdnat)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
|
||||
class TestTake:
|
||||
def test_take(self):
|
||||
# GH#10295
|
||||
idx1 = period_range("2011-01-01", "2011-01-31", freq="D", name="idx")
|
||||
|
||||
for idx in [idx1]:
|
||||
result = idx.take([0])
|
||||
assert result == Period("2011-01-01", freq="D")
|
||||
|
||||
result = idx.take([5])
|
||||
assert result == Period("2011-01-06", freq="D")
|
||||
|
||||
result = idx.take([0, 1, 2])
|
||||
expected = period_range("2011-01-01", "2011-01-03", freq="D", name="idx")
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == "D"
|
||||
assert result.freq == expected.freq
|
||||
|
||||
result = idx.take([0, 2, 4])
|
||||
expected = PeriodIndex(
|
||||
["2011-01-01", "2011-01-03", "2011-01-05"], freq="D", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
result = idx.take([7, 4, 1])
|
||||
expected = PeriodIndex(
|
||||
["2011-01-08", "2011-01-05", "2011-01-02"], freq="D", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
result = idx.take([3, 2, 5])
|
||||
expected = PeriodIndex(
|
||||
["2011-01-04", "2011-01-03", "2011-01-06"], freq="D", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
result = idx.take([-3, 2, 5])
|
||||
expected = PeriodIndex(
|
||||
["2011-01-29", "2011-01-03", "2011-01-06"], freq="D", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.freq == expected.freq
|
||||
assert result.freq == "D"
|
||||
|
||||
def test_take_misc(self):
|
||||
index = period_range(start="1/1/10", end="12/31/12", freq="D", name="idx")
|
||||
expected = PeriodIndex(
|
||||
[
|
||||
datetime(2010, 1, 6),
|
||||
datetime(2010, 1, 7),
|
||||
datetime(2010, 1, 9),
|
||||
datetime(2010, 1, 13),
|
||||
],
|
||||
freq="D",
|
||||
name="idx",
|
||||
)
|
||||
|
||||
taken1 = index.take([5, 6, 8, 12])
|
||||
taken2 = index[[5, 6, 8, 12]]
|
||||
|
||||
for taken in [taken1, taken2]:
|
||||
tm.assert_index_equal(taken, expected)
|
||||
assert isinstance(taken, PeriodIndex)
|
||||
assert taken.freq == index.freq
|
||||
assert taken.name == expected.name
|
||||
|
||||
def test_take_fill_value(self):
|
||||
# GH#12631
|
||||
idx = PeriodIndex(
|
||||
["2011-01-01", "2011-02-01", "2011-03-01"], name="xxx", freq="D"
|
||||
)
|
||||
result = idx.take(np.array([1, 0, -1]))
|
||||
expected = PeriodIndex(
|
||||
["2011-02-01", "2011-01-01", "2011-03-01"], name="xxx", freq="D"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# fill_value
|
||||
result = idx.take(np.array([1, 0, -1]), fill_value=True)
|
||||
expected = PeriodIndex(
|
||||
["2011-02-01", "2011-01-01", "NaT"], name="xxx", freq="D"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# allow_fill=False
|
||||
result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True)
|
||||
expected = PeriodIndex(
|
||||
["2011-02-01", "2011-01-01", "2011-03-01"], name="xxx", freq="D"
|
||||
)
|
||||
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)
|
||||
|
||||
msg = "index -5 is out of bounds for( axis 0 with)? size 3"
|
||||
with pytest.raises(IndexError, match=msg):
|
||||
idx.take(np.array([1, -5]))
|
||||
|
||||
|
||||
class TestGetValue:
|
||||
@pytest.mark.parametrize("freq", ["H", "D"])
|
||||
def test_get_value_datetime_hourly(self, freq):
|
||||
# get_loc and get_value should treat datetime objects symmetrically
|
||||
# TODO: this test used to test get_value, which is removed in 2.0.
|
||||
# should this test be moved somewhere, or is what's left redundant?
|
||||
dti = date_range("2016-01-01", periods=3, freq="MS")
|
||||
pi = dti.to_period(freq)
|
||||
ser = Series(range(7, 10), index=pi)
|
||||
|
||||
ts = dti[0]
|
||||
|
||||
assert pi.get_loc(ts) == 0
|
||||
assert ser[ts] == 7
|
||||
assert ser.loc[ts] == 7
|
||||
|
||||
ts2 = ts + Timedelta(hours=3)
|
||||
if freq == "H":
|
||||
with pytest.raises(KeyError, match="2016-01-01 03:00"):
|
||||
pi.get_loc(ts2)
|
||||
with pytest.raises(KeyError, match="2016-01-01 03:00"):
|
||||
ser[ts2]
|
||||
with pytest.raises(KeyError, match="2016-01-01 03:00"):
|
||||
ser.loc[ts2]
|
||||
else:
|
||||
assert pi.get_loc(ts2) == 0
|
||||
assert ser[ts2] == 7
|
||||
assert ser.loc[ts2] == 7
|
||||
|
||||
|
||||
class TestContains:
|
||||
def test_contains(self):
|
||||
# GH 17717
|
||||
p0 = Period("2017-09-01")
|
||||
p1 = Period("2017-09-02")
|
||||
p2 = Period("2017-09-03")
|
||||
p3 = Period("2017-09-04")
|
||||
|
||||
ps0 = [p0, p1, p2]
|
||||
idx0 = PeriodIndex(ps0)
|
||||
|
||||
for p in ps0:
|
||||
assert p in idx0
|
||||
assert str(p) in idx0
|
||||
|
||||
# GH#31172
|
||||
# Higher-resolution period-like are _not_ considered as contained
|
||||
key = "2017-09-01 00:00:01"
|
||||
assert key not in idx0
|
||||
with pytest.raises(KeyError, match=key):
|
||||
idx0.get_loc(key)
|
||||
|
||||
assert "2017-09" in idx0
|
||||
|
||||
assert p3 not in idx0
|
||||
|
||||
def test_contains_freq_mismatch(self):
|
||||
rng = period_range("2007-01", freq="M", periods=10)
|
||||
|
||||
assert Period("2007-01", freq="M") in rng
|
||||
assert Period("2007-01", freq="D") not in rng
|
||||
assert Period("2007-01", freq="2M") not in rng
|
||||
|
||||
def test_contains_nat(self):
|
||||
# see gh-13582
|
||||
idx = period_range("2007-01", freq="M", periods=10)
|
||||
assert NaT not in idx
|
||||
assert None not in idx
|
||||
assert float("nan") not in idx
|
||||
assert np.nan not in idx
|
||||
|
||||
idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="M")
|
||||
assert NaT in idx
|
||||
assert None in idx
|
||||
assert float("nan") in idx
|
||||
assert np.nan in idx
|
||||
|
||||
|
||||
class TestAsOfLocs:
|
||||
def test_asof_locs_mismatched_type(self):
|
||||
dti = date_range("2016-01-01", periods=3)
|
||||
pi = dti.to_period("D")
|
||||
pi2 = dti.to_period("H")
|
||||
|
||||
mask = np.array([0, 1, 0], dtype=bool)
|
||||
|
||||
msg = "must be DatetimeIndex or PeriodIndex"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pi.asof_locs(pd.Index(pi.asi8, dtype=np.int64), mask)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pi.asof_locs(pd.Index(pi.asi8, dtype=np.float64), mask)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
# TimedeltaIndex
|
||||
pi.asof_locs(dti - dti, mask)
|
||||
|
||||
msg = "Input has different freq=H"
|
||||
with pytest.raises(libperiod.IncompatibleFrequency, match=msg):
|
||||
pi.asof_locs(pi2, mask)
|
@@ -0,0 +1,58 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import IncompatibleFrequency
|
||||
|
||||
from pandas import (
|
||||
Index,
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestJoin:
|
||||
def test_join_outer_indexer(self):
|
||||
pi = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
|
||||
result = pi._outer_indexer(pi)
|
||||
tm.assert_extension_array_equal(result[0], pi._values)
|
||||
tm.assert_numpy_array_equal(result[1], np.arange(len(pi), dtype=np.intp))
|
||||
tm.assert_numpy_array_equal(result[2], np.arange(len(pi), dtype=np.intp))
|
||||
|
||||
def test_joins(self, join_type):
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
|
||||
joined = index.join(index[:-5], how=join_type)
|
||||
|
||||
assert isinstance(joined, PeriodIndex)
|
||||
assert joined.freq == index.freq
|
||||
|
||||
def test_join_self(self, join_type):
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
|
||||
res = index.join(index, how=join_type)
|
||||
assert index is res
|
||||
|
||||
def test_join_does_not_recur(self):
|
||||
df = tm.makeCustomDataframe(
|
||||
3,
|
||||
2,
|
||||
data_gen_f=lambda *args: np.random.default_rng(2).integers(2),
|
||||
c_idx_type="p",
|
||||
r_idx_type="dt",
|
||||
)
|
||||
ser = df.iloc[:2, 0]
|
||||
|
||||
res = ser.index.join(df.columns, how="outer")
|
||||
expected = Index(
|
||||
[ser.index[0], ser.index[1], df.columns[0], df.columns[1]], object
|
||||
)
|
||||
tm.assert_index_equal(res, expected)
|
||||
|
||||
def test_join_mismatched_freq_raises(self):
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
index3 = period_range("1/1/2000", "1/20/2000", freq="2D")
|
||||
msg = r".*Input has different freq=2D from Period\(freq=D\)"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
index.join(index3)
|
@@ -0,0 +1,42 @@
|
||||
from pandas import (
|
||||
Period,
|
||||
PeriodIndex,
|
||||
)
|
||||
|
||||
|
||||
def test_is_monotonic_increasing():
|
||||
# GH#17717
|
||||
p0 = Period("2017-09-01")
|
||||
p1 = Period("2017-09-02")
|
||||
p2 = Period("2017-09-03")
|
||||
|
||||
idx_inc0 = PeriodIndex([p0, p1, p2])
|
||||
idx_inc1 = PeriodIndex([p0, p1, p1])
|
||||
idx_dec0 = PeriodIndex([p2, p1, p0])
|
||||
idx_dec1 = PeriodIndex([p2, p1, p1])
|
||||
idx = PeriodIndex([p1, p2, p0])
|
||||
|
||||
assert idx_inc0.is_monotonic_increasing is True
|
||||
assert idx_inc1.is_monotonic_increasing is True
|
||||
assert idx_dec0.is_monotonic_increasing is False
|
||||
assert idx_dec1.is_monotonic_increasing is False
|
||||
assert idx.is_monotonic_increasing is False
|
||||
|
||||
|
||||
def test_is_monotonic_decreasing():
|
||||
# GH#17717
|
||||
p0 = Period("2017-09-01")
|
||||
p1 = Period("2017-09-02")
|
||||
p2 = Period("2017-09-03")
|
||||
|
||||
idx_inc0 = PeriodIndex([p0, p1, p2])
|
||||
idx_inc1 = PeriodIndex([p0, p1, p1])
|
||||
idx_dec0 = PeriodIndex([p2, p1, p0])
|
||||
idx_dec1 = PeriodIndex([p2, p1, p1])
|
||||
idx = PeriodIndex([p1, p2, p0])
|
||||
|
||||
assert idx_inc0.is_monotonic_decreasing is False
|
||||
assert idx_inc1.is_monotonic_decreasing is False
|
||||
assert idx_dec0.is_monotonic_decreasing is True
|
||||
assert idx_dec1.is_monotonic_decreasing is True
|
||||
assert idx.is_monotonic_decreasing is False
|
@@ -0,0 +1,195 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
DataFrame,
|
||||
PeriodIndex,
|
||||
Series,
|
||||
date_range,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_getitem_periodindex_duplicates_string_slice(self, using_copy_on_write):
|
||||
# monotonic
|
||||
idx = PeriodIndex([2000, 2007, 2007, 2009, 2009], freq="A-JUN")
|
||||
ts = Series(np.random.default_rng(2).standard_normal(len(idx)), index=idx)
|
||||
original = ts.copy()
|
||||
|
||||
result = ts["2007"]
|
||||
expected = ts[1:3]
|
||||
tm.assert_series_equal(result, expected)
|
||||
result[:] = 1
|
||||
if using_copy_on_write:
|
||||
tm.assert_series_equal(ts, original)
|
||||
else:
|
||||
assert (ts[1:3] == 1).all()
|
||||
|
||||
# not monotonic
|
||||
idx = PeriodIndex([2000, 2007, 2007, 2009, 2007], freq="A-JUN")
|
||||
ts = Series(np.random.default_rng(2).standard_normal(len(idx)), index=idx)
|
||||
|
||||
result = ts["2007"]
|
||||
expected = ts[idx == "2007"]
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
def test_getitem_periodindex_quarter_string(self):
|
||||
pi = PeriodIndex(["2Q05", "3Q05", "4Q05", "1Q06", "2Q06"], freq="Q")
|
||||
ser = Series(np.random.default_rng(2).random(len(pi)), index=pi).cumsum()
|
||||
# Todo: fix these accessors!
|
||||
assert ser["05Q4"] == ser.iloc[2]
|
||||
|
||||
def test_pindex_slice_index(self):
|
||||
pi = period_range(start="1/1/10", end="12/31/12", freq="M")
|
||||
s = Series(np.random.default_rng(2).random(len(pi)), index=pi)
|
||||
res = s["2010"]
|
||||
exp = s[0:12]
|
||||
tm.assert_series_equal(res, exp)
|
||||
res = s["2011"]
|
||||
exp = s[12:24]
|
||||
tm.assert_series_equal(res, exp)
|
||||
|
||||
@pytest.mark.parametrize("make_range", [date_range, period_range])
|
||||
def test_range_slice_day(self, make_range):
|
||||
# GH#6716
|
||||
idx = make_range(start="2013/01/01", freq="D", periods=400)
|
||||
|
||||
msg = "slice indices must be integers or None or have an __index__ method"
|
||||
# slices against index should raise IndexError
|
||||
values = [
|
||||
"2014",
|
||||
"2013/02",
|
||||
"2013/01/02",
|
||||
"2013/02/01 9H",
|
||||
"2013/02/01 09:00",
|
||||
]
|
||||
for v in values:
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx[v:]
|
||||
|
||||
s = Series(np.random.default_rng(2).random(len(idx)), index=idx)
|
||||
|
||||
tm.assert_series_equal(s["2013/01/02":], s[1:])
|
||||
tm.assert_series_equal(s["2013/01/02":"2013/01/05"], s[1:5])
|
||||
tm.assert_series_equal(s["2013/02":], s[31:])
|
||||
tm.assert_series_equal(s["2014":], s[365:])
|
||||
|
||||
invalid = ["2013/02/01 9H", "2013/02/01 09:00"]
|
||||
for v in invalid:
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx[v:]
|
||||
|
||||
@pytest.mark.parametrize("make_range", [date_range, period_range])
|
||||
def test_range_slice_seconds(self, make_range):
|
||||
# GH#6716
|
||||
idx = make_range(start="2013/01/01 09:00:00", freq="S", periods=4000)
|
||||
msg = "slice indices must be integers or None or have an __index__ method"
|
||||
|
||||
# slices against index should raise IndexError
|
||||
values = [
|
||||
"2014",
|
||||
"2013/02",
|
||||
"2013/01/02",
|
||||
"2013/02/01 9H",
|
||||
"2013/02/01 09:00",
|
||||
]
|
||||
for v in values:
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx[v:]
|
||||
|
||||
s = Series(np.random.default_rng(2).random(len(idx)), index=idx)
|
||||
|
||||
tm.assert_series_equal(s["2013/01/01 09:05":"2013/01/01 09:10"], s[300:660])
|
||||
tm.assert_series_equal(s["2013/01/01 10:00":"2013/01/01 10:05"], s[3600:3960])
|
||||
tm.assert_series_equal(s["2013/01/01 10H":], s[3600:])
|
||||
tm.assert_series_equal(s[:"2013/01/01 09:30"], s[:1860])
|
||||
for d in ["2013/01/01", "2013/01", "2013"]:
|
||||
tm.assert_series_equal(s[d:], s)
|
||||
|
||||
@pytest.mark.parametrize("make_range", [date_range, period_range])
|
||||
def test_range_slice_outofbounds(self, make_range):
|
||||
# GH#5407
|
||||
idx = make_range(start="2013/10/01", freq="D", periods=10)
|
||||
|
||||
df = DataFrame({"units": [100 + i for i in range(10)]}, index=idx)
|
||||
empty = DataFrame(index=type(idx)([], freq="D"), columns=["units"])
|
||||
empty["units"] = empty["units"].astype("int64")
|
||||
|
||||
tm.assert_frame_equal(df["2013/09/01":"2013/09/30"], empty)
|
||||
tm.assert_frame_equal(df["2013/09/30":"2013/10/02"], df.iloc[:2])
|
||||
tm.assert_frame_equal(df["2013/10/01":"2013/10/02"], df.iloc[:2])
|
||||
tm.assert_frame_equal(df["2013/10/02":"2013/09/30"], empty)
|
||||
tm.assert_frame_equal(df["2013/10/15":"2013/10/17"], empty)
|
||||
tm.assert_frame_equal(df["2013-06":"2013-09"], empty)
|
||||
tm.assert_frame_equal(df["2013-11":"2013-12"], empty)
|
||||
|
||||
@pytest.mark.parametrize("make_range", [date_range, period_range])
|
||||
def test_maybe_cast_slice_bound(self, make_range, frame_or_series):
|
||||
idx = make_range(start="2013/10/01", freq="D", periods=10)
|
||||
|
||||
obj = DataFrame({"units": [100 + i for i in range(10)]}, index=idx)
|
||||
obj = tm.get_obj(obj, frame_or_series)
|
||||
|
||||
msg = (
|
||||
f"cannot do slice indexing on {type(idx).__name__} with "
|
||||
r"these indexers \[foo\] of type str"
|
||||
)
|
||||
|
||||
# Check the lower-level calls are raising where expected.
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx._maybe_cast_slice_bound("foo", "left")
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
idx.get_slice_bound("foo", "left")
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
obj["2013/09/30":"foo"]
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
obj["foo":"2013/09/30"]
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
obj.loc["2013/09/30":"foo"]
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
obj.loc["foo":"2013/09/30"]
|
||||
|
||||
def test_partial_slice_doesnt_require_monotonicity(self):
|
||||
# See also: DatetimeIndex test ofm the same name
|
||||
dti = date_range("2014-01-01", periods=30, freq="30D")
|
||||
pi = dti.to_period("D")
|
||||
|
||||
ser_montonic = Series(np.arange(30), index=pi)
|
||||
|
||||
shuffler = list(range(0, 30, 2)) + list(range(1, 31, 2))
|
||||
ser = ser_montonic.iloc[shuffler]
|
||||
nidx = ser.index
|
||||
|
||||
# Manually identified locations of year==2014
|
||||
indexer_2014 = np.array(
|
||||
[0, 1, 2, 3, 4, 5, 6, 15, 16, 17, 18, 19, 20], dtype=np.intp
|
||||
)
|
||||
assert (nidx[indexer_2014].year == 2014).all()
|
||||
assert not (nidx[~indexer_2014].year == 2014).any()
|
||||
|
||||
result = nidx.get_loc("2014")
|
||||
tm.assert_numpy_array_equal(result, indexer_2014)
|
||||
|
||||
expected = ser.iloc[indexer_2014]
|
||||
result = ser.loc["2014"]
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
result = ser["2014"]
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
# Manually identified locations where ser.index is within Mat 2015
|
||||
indexer_may2015 = np.array([23], dtype=np.intp)
|
||||
assert nidx[23].year == 2015 and nidx[23].month == 5
|
||||
|
||||
result = nidx.get_loc("May 2015")
|
||||
tm.assert_numpy_array_equal(result, indexer_may2015)
|
||||
|
||||
expected = ser.iloc[indexer_may2015]
|
||||
result = ser.loc["May 2015"]
|
||||
tm.assert_series_equal(result, expected)
|
||||
|
||||
result = ser["May 2015"]
|
||||
tm.assert_series_equal(result, expected)
|
@@ -0,0 +1,320 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs.period import IncompatibleFrequency
|
||||
|
||||
from pandas import (
|
||||
Index,
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
Series,
|
||||
date_range,
|
||||
offsets,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_make_time_series(self):
|
||||
index = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
series = Series(1, index=index)
|
||||
assert isinstance(series, Series)
|
||||
|
||||
def test_view_asi8(self):
|
||||
idx = PeriodIndex([], freq="M")
|
||||
|
||||
exp = np.array([], dtype=np.int64)
|
||||
tm.assert_numpy_array_equal(idx.view("i8"), exp)
|
||||
tm.assert_numpy_array_equal(idx.asi8, exp)
|
||||
|
||||
idx = PeriodIndex(["2011-01", NaT], freq="M")
|
||||
|
||||
exp = np.array([492, -9223372036854775808], dtype=np.int64)
|
||||
tm.assert_numpy_array_equal(idx.view("i8"), exp)
|
||||
tm.assert_numpy_array_equal(idx.asi8, exp)
|
||||
|
||||
exp = np.array([14975, -9223372036854775808], dtype=np.int64)
|
||||
idx = PeriodIndex(["2011-01-01", NaT], freq="D")
|
||||
tm.assert_numpy_array_equal(idx.view("i8"), exp)
|
||||
tm.assert_numpy_array_equal(idx.asi8, exp)
|
||||
|
||||
def test_values(self):
|
||||
idx = PeriodIndex([], freq="M")
|
||||
|
||||
exp = np.array([], dtype=object)
|
||||
tm.assert_numpy_array_equal(idx.values, exp)
|
||||
tm.assert_numpy_array_equal(idx.to_numpy(), exp)
|
||||
|
||||
exp = np.array([], dtype=np.int64)
|
||||
tm.assert_numpy_array_equal(idx.asi8, exp)
|
||||
|
||||
idx = PeriodIndex(["2011-01", NaT], freq="M")
|
||||
|
||||
exp = np.array([Period("2011-01", freq="M"), NaT], dtype=object)
|
||||
tm.assert_numpy_array_equal(idx.values, exp)
|
||||
tm.assert_numpy_array_equal(idx.to_numpy(), exp)
|
||||
exp = np.array([492, -9223372036854775808], dtype=np.int64)
|
||||
tm.assert_numpy_array_equal(idx.asi8, exp)
|
||||
|
||||
idx = PeriodIndex(["2011-01-01", NaT], freq="D")
|
||||
|
||||
exp = np.array([Period("2011-01-01", freq="D"), NaT], dtype=object)
|
||||
tm.assert_numpy_array_equal(idx.values, exp)
|
||||
tm.assert_numpy_array_equal(idx.to_numpy(), exp)
|
||||
exp = np.array([14975, -9223372036854775808], dtype=np.int64)
|
||||
tm.assert_numpy_array_equal(idx.asi8, exp)
|
||||
|
||||
def test_period_index_length(self):
|
||||
pi = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
assert len(pi) == 9
|
||||
|
||||
pi = period_range(freq="Q", start="1/1/2001", end="12/1/2009")
|
||||
assert len(pi) == 4 * 9
|
||||
|
||||
pi = period_range(freq="M", start="1/1/2001", end="12/1/2009")
|
||||
assert len(pi) == 12 * 9
|
||||
|
||||
msg = "Period with BDay freq is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
start = Period("02-Apr-2005", "B")
|
||||
i1 = period_range(start=start, periods=20)
|
||||
assert len(i1) == 20
|
||||
assert i1.freq == start.freq
|
||||
assert i1[0] == start
|
||||
|
||||
end_intv = Period("2006-12-31", "W")
|
||||
i1 = period_range(end=end_intv, periods=10)
|
||||
assert len(i1) == 10
|
||||
assert i1.freq == end_intv.freq
|
||||
assert i1[-1] == end_intv
|
||||
|
||||
end_intv = Period("2006-12-31", "1w")
|
||||
i2 = period_range(end=end_intv, periods=10)
|
||||
assert len(i1) == len(i2)
|
||||
assert (i1 == i2).all()
|
||||
assert i1.freq == i2.freq
|
||||
|
||||
msg = "start and end must have same freq"
|
||||
msg2 = "Period with BDay freq is deprecated"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
period_range(start=start, end=end_intv)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
end_intv = Period("2005-05-01", "B")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
i1 = period_range(start=start, end=end_intv)
|
||||
|
||||
msg = (
|
||||
"Of the three parameters: start, end, and periods, exactly two "
|
||||
"must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start=start)
|
||||
|
||||
# infer freq from first element
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
i2 = PeriodIndex([end_intv, Period("2005-05-05", "B")])
|
||||
assert len(i2) == 2
|
||||
assert i2[0] == end_intv
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg2):
|
||||
i2 = PeriodIndex(np.array([end_intv, Period("2005-05-05", "B")]))
|
||||
assert len(i2) == 2
|
||||
assert i2[0] == end_intv
|
||||
|
||||
# Mixed freq should fail
|
||||
vals = [end_intv, Period("2006-12-31", "w")]
|
||||
msg = r"Input has different freq=W-SUN from PeriodIndex\(freq=B\)"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
PeriodIndex(vals)
|
||||
vals = np.array(vals)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(vals)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"field",
|
||||
[
|
||||
"year",
|
||||
"month",
|
||||
"day",
|
||||
"hour",
|
||||
"minute",
|
||||
"second",
|
||||
"weekofyear",
|
||||
"week",
|
||||
"dayofweek",
|
||||
"day_of_week",
|
||||
"dayofyear",
|
||||
"day_of_year",
|
||||
"quarter",
|
||||
"qyear",
|
||||
"days_in_month",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"periodindex",
|
||||
[
|
||||
period_range(freq="A", start="1/1/2001", end="12/1/2005"),
|
||||
period_range(freq="Q", start="1/1/2001", end="12/1/2002"),
|
||||
period_range(freq="M", start="1/1/2001", end="1/1/2002"),
|
||||
period_range(freq="D", start="12/1/2001", end="6/1/2001"),
|
||||
period_range(freq="H", start="12/31/2001", end="1/1/2002 23:00"),
|
||||
period_range(freq="Min", start="12/31/2001", end="1/1/2002 00:20"),
|
||||
period_range(
|
||||
freq="S", start="12/31/2001 00:00:00", end="12/31/2001 00:05:00"
|
||||
),
|
||||
period_range(end=Period("2006-12-31", "W"), periods=10),
|
||||
],
|
||||
)
|
||||
def test_fields(self, periodindex, field):
|
||||
periods = list(periodindex)
|
||||
ser = Series(periodindex)
|
||||
|
||||
field_idx = getattr(periodindex, field)
|
||||
assert len(periodindex) == len(field_idx)
|
||||
for x, val in zip(periods, field_idx):
|
||||
assert getattr(x, field) == val
|
||||
|
||||
if len(ser) == 0:
|
||||
return
|
||||
|
||||
field_s = getattr(ser.dt, field)
|
||||
assert len(periodindex) == len(field_s)
|
||||
for x, val in zip(periods, field_s):
|
||||
assert getattr(x, field) == val
|
||||
|
||||
def test_is_(self):
|
||||
create_index = lambda: period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
index = create_index()
|
||||
assert index.is_(index)
|
||||
assert not index.is_(create_index())
|
||||
assert index.is_(index.view())
|
||||
assert index.is_(index.view().view().view().view().view())
|
||||
assert index.view().is_(index)
|
||||
ind2 = index.view()
|
||||
index.name = "Apple"
|
||||
assert ind2.is_(index)
|
||||
assert not index.is_(index[:])
|
||||
assert not index.is_(index.asfreq("M"))
|
||||
assert not index.is_(index.asfreq("A"))
|
||||
|
||||
assert not index.is_(index - 2)
|
||||
assert not index.is_(index - 0)
|
||||
|
||||
def test_index_unique(self):
|
||||
idx = PeriodIndex([2000, 2007, 2007, 2009, 2009], freq="A-JUN")
|
||||
expected = PeriodIndex([2000, 2007, 2009], freq="A-JUN")
|
||||
tm.assert_index_equal(idx.unique(), expected)
|
||||
assert idx.nunique() == 3
|
||||
|
||||
def test_negative_ordinals(self):
|
||||
Period(ordinal=-1000, freq="A")
|
||||
Period(ordinal=0, freq="A")
|
||||
|
||||
idx1 = PeriodIndex(ordinal=[-1, 0, 1], freq="A")
|
||||
idx2 = PeriodIndex(ordinal=np.array([-1, 0, 1]), freq="A")
|
||||
tm.assert_index_equal(idx1, idx2)
|
||||
|
||||
def test_pindex_fieldaccessor_nat(self):
|
||||
idx = PeriodIndex(
|
||||
["2011-01", "2011-02", "NaT", "2012-03", "2012-04"], freq="D", name="name"
|
||||
)
|
||||
|
||||
exp = Index([2011, 2011, -1, 2012, 2012], dtype=np.int64, name="name")
|
||||
tm.assert_index_equal(idx.year, exp)
|
||||
exp = Index([1, 2, -1, 3, 4], dtype=np.int64, name="name")
|
||||
tm.assert_index_equal(idx.month, exp)
|
||||
|
||||
def test_pindex_multiples(self):
|
||||
expected = PeriodIndex(
|
||||
["2011-01", "2011-03", "2011-05", "2011-07", "2011-09", "2011-11"],
|
||||
freq="2M",
|
||||
)
|
||||
|
||||
pi = period_range(start="1/1/11", end="12/31/11", freq="2M")
|
||||
tm.assert_index_equal(pi, expected)
|
||||
assert pi.freq == offsets.MonthEnd(2)
|
||||
assert pi.freqstr == "2M"
|
||||
|
||||
pi = period_range(start="1/1/11", periods=6, freq="2M")
|
||||
tm.assert_index_equal(pi, expected)
|
||||
assert pi.freq == offsets.MonthEnd(2)
|
||||
assert pi.freqstr == "2M"
|
||||
|
||||
@pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning")
|
||||
@pytest.mark.filterwarnings("ignore:Period with BDay freq:FutureWarning")
|
||||
def test_iteration(self):
|
||||
index = period_range(start="1/1/10", periods=4, freq="B")
|
||||
|
||||
result = list(index)
|
||||
assert isinstance(result[0], Period)
|
||||
assert result[0].freq == index.freq
|
||||
|
||||
def test_with_multi_index(self):
|
||||
# #1705
|
||||
index = date_range("1/1/2012", periods=4, freq="12H")
|
||||
index_as_arrays = [index.to_period(freq="D"), index.hour]
|
||||
|
||||
s = Series([0, 1, 2, 3], index_as_arrays)
|
||||
|
||||
assert isinstance(s.index.levels[0], PeriodIndex)
|
||||
|
||||
assert isinstance(s.index.values[0][0], Period)
|
||||
|
||||
def test_map(self):
|
||||
# test_map_dictlike generally tests
|
||||
|
||||
index = PeriodIndex([2005, 2007, 2009], freq="A")
|
||||
result = index.map(lambda x: x.ordinal)
|
||||
exp = Index([x.ordinal for x in index])
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
def test_format_empty(self):
|
||||
# GH35712
|
||||
empty_idx = PeriodIndex([], freq="A")
|
||||
assert empty_idx.format() == []
|
||||
assert empty_idx.format(name=True) == [""]
|
||||
|
||||
|
||||
def test_maybe_convert_timedelta():
|
||||
pi = PeriodIndex(["2000", "2001"], freq="D")
|
||||
offset = offsets.Day(2)
|
||||
assert pi._maybe_convert_timedelta(offset) == 2
|
||||
assert pi._maybe_convert_timedelta(2) == 2
|
||||
|
||||
offset = offsets.BusinessDay()
|
||||
msg = r"Input has different freq=B from PeriodIndex\(freq=D\)"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
pi._maybe_convert_timedelta(offset)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("array", [True, False])
|
||||
def test_dunder_array(array):
|
||||
obj = PeriodIndex(["2000-01-01", "2001-01-01"], freq="D")
|
||||
if array:
|
||||
obj = obj._data
|
||||
|
||||
expected = np.array([obj[0], obj[1]], dtype=object)
|
||||
result = np.array(obj)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
result = np.asarray(obj)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
expected = obj.asi8
|
||||
for dtype in ["i8", "int64", np.int64]:
|
||||
result = np.array(obj, dtype=dtype)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
result = np.asarray(obj, dtype=dtype)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
for dtype in ["float64", "int32", "uint64"]:
|
||||
msg = "argument must be"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
np.array(obj, dtype=dtype)
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
np.array(obj, dtype=getattr(np, dtype))
|
@@ -0,0 +1,121 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
date_range,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodRange:
|
||||
def test_required_arguments(self):
|
||||
msg = (
|
||||
"Of the three parameters: start, end, and periods, exactly two "
|
||||
"must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range("2011-1-1", "2012-1-1", "B")
|
||||
|
||||
@pytest.mark.parametrize("freq", ["D", "W", "M", "Q", "A"])
|
||||
def test_construction_from_string(self, freq):
|
||||
# non-empty
|
||||
expected = date_range(
|
||||
start="2017-01-01", periods=5, freq=freq, name="foo"
|
||||
).to_period()
|
||||
start, end = str(expected[0]), str(expected[-1])
|
||||
|
||||
result = period_range(start=start, end=end, freq=freq, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=start, periods=5, freq=freq, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=5, freq=freq, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# empty
|
||||
expected = PeriodIndex([], freq=freq, name="foo")
|
||||
|
||||
result = period_range(start=start, periods=0, freq=freq, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=0, freq=freq, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=end, end=start, freq=freq, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_construction_from_period(self):
|
||||
# upsampling
|
||||
start, end = Period("2017Q1", freq="Q"), Period("2018Q1", freq="Q")
|
||||
expected = date_range(
|
||||
start="2017-03-31", end="2018-03-31", freq="M", name="foo"
|
||||
).to_period()
|
||||
result = period_range(start=start, end=end, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# downsampling
|
||||
start, end = Period("2017-1", freq="M"), Period("2019-12", freq="M")
|
||||
expected = date_range(
|
||||
start="2017-01-31", end="2019-12-31", freq="Q", name="foo"
|
||||
).to_period()
|
||||
result = period_range(start=start, end=end, freq="Q", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# test for issue # 21793
|
||||
start, end = Period("2017Q1", freq="Q"), Period("2018Q1", freq="Q")
|
||||
idx = period_range(start=start, end=end, freq="Q", name="foo")
|
||||
result = idx == idx.values
|
||||
expected = np.array([True, True, True, True, True])
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# empty
|
||||
expected = PeriodIndex([], freq="W", name="foo")
|
||||
|
||||
result = period_range(start=start, periods=0, freq="W", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=0, freq="W", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=end, end=start, freq="W", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_errors(self):
|
||||
# not enough params
|
||||
msg = (
|
||||
"Of the three parameters: start, end, and periods, "
|
||||
"exactly two must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2017Q1")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(end="2017Q1")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(periods=5)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range()
|
||||
|
||||
# too many params
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2017Q1", end="2018Q1", periods=8, freq="Q")
|
||||
|
||||
# start/end NaT
|
||||
msg = "start and end must not be NaT"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start=NaT, end="2018Q1")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2017Q1", end=NaT)
|
||||
|
||||
# invalid periods param
|
||||
msg = "periods must be a number, got foo"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
period_range(start="2017Q1", periods="foo")
|
@@ -0,0 +1,26 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
NaT,
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
from pandas.tseries import offsets
|
||||
|
||||
|
||||
class TestPickle:
|
||||
@pytest.mark.parametrize("freq", ["D", "M", "A"])
|
||||
def test_pickle_round_trip(self, freq):
|
||||
idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.nan], freq=freq)
|
||||
result = tm.round_trip_pickle(idx)
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
def test_pickle_freq(self):
|
||||
# GH#2891
|
||||
prng = period_range("1/1/2011", "1/1/2012", freq="M")
|
||||
new_prng = tm.round_trip_pickle(prng)
|
||||
assert new_prng.freq == offsets.MonthEnd()
|
||||
assert new_prng.freqstr == "M"
|
@@ -0,0 +1,23 @@
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class TestResolution:
|
||||
@pytest.mark.parametrize(
|
||||
"freq,expected",
|
||||
[
|
||||
("A", "year"),
|
||||
("Q", "quarter"),
|
||||
("M", "month"),
|
||||
("D", "day"),
|
||||
("H", "hour"),
|
||||
("T", "minute"),
|
||||
("S", "second"),
|
||||
("L", "millisecond"),
|
||||
("U", "microsecond"),
|
||||
],
|
||||
)
|
||||
def test_resolution(self, freq, expected):
|
||||
idx = pd.period_range(start="2013-04-01", periods=30, freq=freq)
|
||||
assert idx.resolution == expected
|
@@ -0,0 +1,38 @@
|
||||
"""Tests for PeriodIndex behaving like a vectorized Period scalar"""
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
Timedelta,
|
||||
date_range,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndexOps:
|
||||
def test_start_time(self):
|
||||
# GH#17157
|
||||
index = period_range(freq="M", start="2016-01-01", end="2016-05-31")
|
||||
expected_index = date_range("2016-01-01", end="2016-05-31", freq="MS")
|
||||
tm.assert_index_equal(index.start_time, expected_index)
|
||||
|
||||
def test_end_time(self):
|
||||
# GH#17157
|
||||
index = period_range(freq="M", start="2016-01-01", end="2016-05-31")
|
||||
expected_index = date_range("2016-01-01", end="2016-05-31", freq="M")
|
||||
expected_index += Timedelta(1, "D") - Timedelta(1, "ns")
|
||||
tm.assert_index_equal(index.end_time, expected_index)
|
||||
|
||||
@pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning")
|
||||
@pytest.mark.filterwarnings(
|
||||
"ignore:Period with BDay freq is deprecated:FutureWarning"
|
||||
)
|
||||
def test_end_time_business_friday(self):
|
||||
# GH#34449
|
||||
pi = period_range("1990-01-05", freq="B", periods=1)
|
||||
result = pi.end_time
|
||||
|
||||
dti = date_range("1990-01-05", freq="D", periods=1)._with_freq(None)
|
||||
expected = dti + Timedelta(days=1, nanoseconds=-1)
|
||||
tm.assert_index_equal(result, expected)
|
@@ -0,0 +1,80 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import IncompatibleFrequency
|
||||
|
||||
from pandas import (
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestSearchsorted:
|
||||
@pytest.mark.parametrize("freq", ["D", "2D"])
|
||||
def test_searchsorted(self, freq):
|
||||
pidx = PeriodIndex(
|
||||
["2014-01-01", "2014-01-02", "2014-01-03", "2014-01-04", "2014-01-05"],
|
||||
freq=freq,
|
||||
)
|
||||
|
||||
p1 = Period("2014-01-01", freq=freq)
|
||||
assert pidx.searchsorted(p1) == 0
|
||||
|
||||
p2 = Period("2014-01-04", freq=freq)
|
||||
assert pidx.searchsorted(p2) == 3
|
||||
|
||||
assert pidx.searchsorted(NaT) == 5
|
||||
|
||||
msg = "Input has different freq=H from PeriodArray"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
pidx.searchsorted(Period("2014-01-01", freq="H"))
|
||||
|
||||
msg = "Input has different freq=5D from PeriodArray"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
pidx.searchsorted(Period("2014-01-01", freq="5D"))
|
||||
|
||||
def test_searchsorted_different_argument_classes(self, listlike_box):
|
||||
pidx = PeriodIndex(
|
||||
["2014-01-01", "2014-01-02", "2014-01-03", "2014-01-04", "2014-01-05"],
|
||||
freq="D",
|
||||
)
|
||||
result = pidx.searchsorted(listlike_box(pidx))
|
||||
expected = np.arange(len(pidx), dtype=result.dtype)
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
result = pidx._data.searchsorted(listlike_box(pidx))
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
def test_searchsorted_invalid(self):
|
||||
pidx = PeriodIndex(
|
||||
["2014-01-01", "2014-01-02", "2014-01-03", "2014-01-04", "2014-01-05"],
|
||||
freq="D",
|
||||
)
|
||||
|
||||
other = np.array([0, 1], dtype=np.int64)
|
||||
|
||||
msg = "|".join(
|
||||
[
|
||||
"searchsorted requires compatible dtype or scalar",
|
||||
"value should be a 'Period', 'NaT', or array of those. Got",
|
||||
]
|
||||
)
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pidx.searchsorted(other)
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pidx.searchsorted(other.astype("timedelta64[ns]"))
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pidx.searchsorted(np.timedelta64(4))
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pidx.searchsorted(np.timedelta64("NaT", "ms"))
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pidx.searchsorted(np.datetime64(4, "ns"))
|
||||
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
pidx.searchsorted(np.datetime64("NaT", "ns"))
|
@@ -0,0 +1,361 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
date_range,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def _permute(obj):
|
||||
return obj.take(np.random.default_rng(2).permutation(len(obj)))
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_union(self, sort):
|
||||
# union
|
||||
other1 = period_range("1/1/2000", freq="D", periods=5)
|
||||
rng1 = period_range("1/6/2000", freq="D", periods=5)
|
||||
expected1 = PeriodIndex(
|
||||
[
|
||||
"2000-01-06",
|
||||
"2000-01-07",
|
||||
"2000-01-08",
|
||||
"2000-01-09",
|
||||
"2000-01-10",
|
||||
"2000-01-01",
|
||||
"2000-01-02",
|
||||
"2000-01-03",
|
||||
"2000-01-04",
|
||||
"2000-01-05",
|
||||
],
|
||||
freq="D",
|
||||
)
|
||||
|
||||
rng2 = period_range("1/1/2000", freq="D", periods=5)
|
||||
other2 = period_range("1/4/2000", freq="D", periods=5)
|
||||
expected2 = period_range("1/1/2000", freq="D", periods=8)
|
||||
|
||||
rng3 = period_range("1/1/2000", freq="D", periods=5)
|
||||
other3 = PeriodIndex([], freq="D")
|
||||
expected3 = period_range("1/1/2000", freq="D", periods=5)
|
||||
|
||||
rng4 = period_range("2000-01-01 09:00", freq="H", periods=5)
|
||||
other4 = period_range("2000-01-02 09:00", freq="H", periods=5)
|
||||
expected4 = PeriodIndex(
|
||||
[
|
||||
"2000-01-01 09:00",
|
||||
"2000-01-01 10:00",
|
||||
"2000-01-01 11:00",
|
||||
"2000-01-01 12:00",
|
||||
"2000-01-01 13:00",
|
||||
"2000-01-02 09:00",
|
||||
"2000-01-02 10:00",
|
||||
"2000-01-02 11:00",
|
||||
"2000-01-02 12:00",
|
||||
"2000-01-02 13:00",
|
||||
],
|
||||
freq="H",
|
||||
)
|
||||
|
||||
rng5 = PeriodIndex(
|
||||
["2000-01-01 09:01", "2000-01-01 09:03", "2000-01-01 09:05"], freq="T"
|
||||
)
|
||||
other5 = PeriodIndex(
|
||||
["2000-01-01 09:01", "2000-01-01 09:05", "2000-01-01 09:08"], freq="T"
|
||||
)
|
||||
expected5 = PeriodIndex(
|
||||
[
|
||||
"2000-01-01 09:01",
|
||||
"2000-01-01 09:03",
|
||||
"2000-01-01 09:05",
|
||||
"2000-01-01 09:08",
|
||||
],
|
||||
freq="T",
|
||||
)
|
||||
|
||||
rng6 = period_range("2000-01-01", freq="M", periods=7)
|
||||
other6 = period_range("2000-04-01", freq="M", periods=7)
|
||||
expected6 = period_range("2000-01-01", freq="M", periods=10)
|
||||
|
||||
rng7 = period_range("2003-01-01", freq="A", periods=5)
|
||||
other7 = period_range("1998-01-01", freq="A", periods=8)
|
||||
expected7 = PeriodIndex(
|
||||
[
|
||||
"2003",
|
||||
"2004",
|
||||
"2005",
|
||||
"2006",
|
||||
"2007",
|
||||
"1998",
|
||||
"1999",
|
||||
"2000",
|
||||
"2001",
|
||||
"2002",
|
||||
],
|
||||
freq="A",
|
||||
)
|
||||
|
||||
rng8 = PeriodIndex(
|
||||
["1/3/2000", "1/2/2000", "1/1/2000", "1/5/2000", "1/4/2000"], freq="D"
|
||||
)
|
||||
other8 = period_range("1/6/2000", freq="D", periods=5)
|
||||
expected8 = PeriodIndex(
|
||||
[
|
||||
"1/3/2000",
|
||||
"1/2/2000",
|
||||
"1/1/2000",
|
||||
"1/5/2000",
|
||||
"1/4/2000",
|
||||
"1/6/2000",
|
||||
"1/7/2000",
|
||||
"1/8/2000",
|
||||
"1/9/2000",
|
||||
"1/10/2000",
|
||||
],
|
||||
freq="D",
|
||||
)
|
||||
|
||||
for rng, other, expected in [
|
||||
(rng1, other1, expected1),
|
||||
(rng2, other2, expected2),
|
||||
(rng3, other3, expected3),
|
||||
(rng4, other4, expected4),
|
||||
(rng5, other5, expected5),
|
||||
(rng6, other6, expected6),
|
||||
(rng7, other7, expected7),
|
||||
(rng8, other8, expected8),
|
||||
]:
|
||||
result_union = rng.union(other, sort=sort)
|
||||
if sort is None:
|
||||
expected = expected.sort_values()
|
||||
tm.assert_index_equal(result_union, expected)
|
||||
|
||||
def test_union_misc(self, sort):
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
|
||||
result = index[:-5].union(index[10:], sort=sort)
|
||||
tm.assert_index_equal(result, index)
|
||||
|
||||
# not in order
|
||||
result = _permute(index[:-5]).union(_permute(index[10:]), sort=sort)
|
||||
if sort is None:
|
||||
tm.assert_index_equal(result, index)
|
||||
assert tm.equalContents(result, index)
|
||||
|
||||
# cast if different frequencies
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
index2 = period_range("1/1/2000", "1/20/2000", freq="W-WED")
|
||||
result = index.union(index2, sort=sort)
|
||||
expected = index.astype(object).union(index2.astype(object), sort=sort)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_intersection(self, sort):
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
|
||||
result = index[:-5].intersection(index[10:], sort=sort)
|
||||
tm.assert_index_equal(result, index[10:-5])
|
||||
|
||||
# not in order
|
||||
left = _permute(index[:-5])
|
||||
right = _permute(index[10:])
|
||||
result = left.intersection(right, sort=sort)
|
||||
if sort is None:
|
||||
tm.assert_index_equal(result, index[10:-5])
|
||||
assert tm.equalContents(result, index[10:-5])
|
||||
|
||||
# cast if different frequencies
|
||||
index = period_range("1/1/2000", "1/20/2000", freq="D")
|
||||
index2 = period_range("1/1/2000", "1/20/2000", freq="W-WED")
|
||||
|
||||
result = index.intersection(index2, sort=sort)
|
||||
expected = pd.Index([], dtype=object)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
index3 = period_range("1/1/2000", "1/20/2000", freq="2D")
|
||||
result = index.intersection(index3, sort=sort)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_intersection_cases(self, sort):
|
||||
base = period_range("6/1/2000", "6/30/2000", freq="D", name="idx")
|
||||
|
||||
# if target has the same name, it is preserved
|
||||
rng2 = period_range("5/15/2000", "6/20/2000", freq="D", name="idx")
|
||||
expected2 = period_range("6/1/2000", "6/20/2000", freq="D", name="idx")
|
||||
|
||||
# if target name is different, it will be reset
|
||||
rng3 = period_range("5/15/2000", "6/20/2000", freq="D", name="other")
|
||||
expected3 = period_range("6/1/2000", "6/20/2000", freq="D", name=None)
|
||||
|
||||
rng4 = period_range("7/1/2000", "7/31/2000", freq="D", name="idx")
|
||||
expected4 = PeriodIndex([], name="idx", freq="D")
|
||||
|
||||
for rng, expected in [
|
||||
(rng2, expected2),
|
||||
(rng3, expected3),
|
||||
(rng4, expected4),
|
||||
]:
|
||||
result = base.intersection(rng, sort=sort)
|
||||
tm.assert_index_equal(result, expected)
|
||||
assert result.name == expected.name
|
||||
assert result.freq == expected.freq
|
||||
|
||||
# non-monotonic
|
||||
base = PeriodIndex(
|
||||
["2011-01-05", "2011-01-04", "2011-01-02", "2011-01-03"],
|
||||
freq="D",
|
||||
name="idx",
|
||||
)
|
||||
|
||||
rng2 = PeriodIndex(
|
||||
["2011-01-04", "2011-01-02", "2011-02-02", "2011-02-03"],
|
||||
freq="D",
|
||||
name="idx",
|
||||
)
|
||||
expected2 = PeriodIndex(["2011-01-04", "2011-01-02"], freq="D", name="idx")
|
||||
|
||||
rng3 = PeriodIndex(
|
||||
["2011-01-04", "2011-01-02", "2011-02-02", "2011-02-03"],
|
||||
freq="D",
|
||||
name="other",
|
||||
)
|
||||
expected3 = PeriodIndex(["2011-01-04", "2011-01-02"], freq="D", name=None)
|
||||
|
||||
rng4 = period_range("7/1/2000", "7/31/2000", freq="D", name="idx")
|
||||
expected4 = PeriodIndex([], freq="D", name="idx")
|
||||
|
||||
for rng, expected in [
|
||||
(rng2, expected2),
|
||||
(rng3, expected3),
|
||||
(rng4, expected4),
|
||||
]:
|
||||
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 == "D"
|
||||
|
||||
# empty same freq
|
||||
rng = date_range("6/1/2000", "6/15/2000", freq="T")
|
||||
result = rng[0:0].intersection(rng)
|
||||
assert len(result) == 0
|
||||
|
||||
result = rng.intersection(rng[0:0])
|
||||
assert len(result) == 0
|
||||
|
||||
def test_difference(self, sort):
|
||||
# diff
|
||||
period_rng = ["1/3/2000", "1/2/2000", "1/1/2000", "1/5/2000", "1/4/2000"]
|
||||
rng1 = PeriodIndex(period_rng, freq="D")
|
||||
other1 = period_range("1/6/2000", freq="D", periods=5)
|
||||
expected1 = rng1
|
||||
|
||||
rng2 = PeriodIndex(period_rng, freq="D")
|
||||
other2 = period_range("1/4/2000", freq="D", periods=5)
|
||||
expected2 = PeriodIndex(["1/3/2000", "1/2/2000", "1/1/2000"], freq="D")
|
||||
|
||||
rng3 = PeriodIndex(period_rng, freq="D")
|
||||
other3 = PeriodIndex([], freq="D")
|
||||
expected3 = rng3
|
||||
|
||||
period_rng = [
|
||||
"2000-01-01 10:00",
|
||||
"2000-01-01 09:00",
|
||||
"2000-01-01 12:00",
|
||||
"2000-01-01 11:00",
|
||||
"2000-01-01 13:00",
|
||||
]
|
||||
rng4 = PeriodIndex(period_rng, freq="H")
|
||||
other4 = period_range("2000-01-02 09:00", freq="H", periods=5)
|
||||
expected4 = rng4
|
||||
|
||||
rng5 = PeriodIndex(
|
||||
["2000-01-01 09:03", "2000-01-01 09:01", "2000-01-01 09:05"], freq="T"
|
||||
)
|
||||
other5 = PeriodIndex(["2000-01-01 09:01", "2000-01-01 09:05"], freq="T")
|
||||
expected5 = PeriodIndex(["2000-01-01 09:03"], freq="T")
|
||||
|
||||
period_rng = [
|
||||
"2000-02-01",
|
||||
"2000-01-01",
|
||||
"2000-06-01",
|
||||
"2000-07-01",
|
||||
"2000-05-01",
|
||||
"2000-03-01",
|
||||
"2000-04-01",
|
||||
]
|
||||
rng6 = PeriodIndex(period_rng, freq="M")
|
||||
other6 = period_range("2000-04-01", freq="M", periods=7)
|
||||
expected6 = PeriodIndex(["2000-02-01", "2000-01-01", "2000-03-01"], freq="M")
|
||||
|
||||
period_rng = ["2003", "2007", "2006", "2005", "2004"]
|
||||
rng7 = PeriodIndex(period_rng, freq="A")
|
||||
other7 = period_range("1998-01-01", freq="A", periods=8)
|
||||
expected7 = PeriodIndex(["2007", "2006"], freq="A")
|
||||
|
||||
for rng, other, expected in [
|
||||
(rng1, other1, expected1),
|
||||
(rng2, other2, expected2),
|
||||
(rng3, other3, expected3),
|
||||
(rng4, other4, expected4),
|
||||
(rng5, other5, expected5),
|
||||
(rng6, other6, expected6),
|
||||
(rng7, other7, expected7),
|
||||
]:
|
||||
result_difference = rng.difference(other, sort=sort)
|
||||
if sort is None and len(other):
|
||||
# We dont sort (yet?) when empty GH#24959
|
||||
expected = expected.sort_values()
|
||||
tm.assert_index_equal(result_difference, expected)
|
||||
|
||||
def test_difference_freq(self, sort):
|
||||
# GH14323: difference of Period MUST preserve frequency
|
||||
# but the ability to union results must be preserved
|
||||
|
||||
index = period_range("20160920", "20160925", freq="D")
|
||||
|
||||
other = period_range("20160921", "20160924", freq="D")
|
||||
expected = PeriodIndex(["20160920", "20160925"], freq="D")
|
||||
idx_diff = index.difference(other, sort)
|
||||
tm.assert_index_equal(idx_diff, expected)
|
||||
tm.assert_attr_equal("freq", idx_diff, expected)
|
||||
|
||||
other = period_range("20160922", "20160925", freq="D")
|
||||
idx_diff = index.difference(other, sort)
|
||||
expected = PeriodIndex(["20160920", "20160921"], freq="D")
|
||||
tm.assert_index_equal(idx_diff, expected)
|
||||
tm.assert_attr_equal("freq", idx_diff, expected)
|
||||
|
||||
def test_intersection_equal_duplicates(self):
|
||||
# GH#38302
|
||||
idx = period_range("2011-01-01", periods=2)
|
||||
idx_dup = idx.append(idx)
|
||||
result = idx_dup.intersection(idx_dup)
|
||||
tm.assert_index_equal(result, idx)
|
||||
|
||||
@pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning")
|
||||
def test_union_duplicates(self):
|
||||
# GH#36289
|
||||
idx = period_range("2011-01-01", periods=2)
|
||||
idx_dup = idx.append(idx)
|
||||
|
||||
idx2 = period_range("2011-01-02", periods=2)
|
||||
idx2_dup = idx2.append(idx2)
|
||||
result = idx_dup.union(idx2_dup)
|
||||
|
||||
expected = PeriodIndex(
|
||||
[
|
||||
"2011-01-01",
|
||||
"2011-01-01",
|
||||
"2011-01-02",
|
||||
"2011-01-02",
|
||||
"2011-01-03",
|
||||
"2011-01-03",
|
||||
],
|
||||
freq="D",
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
@@ -0,0 +1,52 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
Period,
|
||||
PeriodIndex,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodRepresentation:
|
||||
"""
|
||||
Wish to match NumPy units
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq, base_date",
|
||||
[
|
||||
("W-THU", "1970-01-01"),
|
||||
("D", "1970-01-01"),
|
||||
("B", "1970-01-01"),
|
||||
("H", "1970-01-01"),
|
||||
("T", "1970-01-01"),
|
||||
("S", "1970-01-01"),
|
||||
("L", "1970-01-01"),
|
||||
("U", "1970-01-01"),
|
||||
("N", "1970-01-01"),
|
||||
("M", "1970-01"),
|
||||
("A", 1970),
|
||||
],
|
||||
)
|
||||
@pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning")
|
||||
@pytest.mark.filterwarnings(
|
||||
"ignore:Period with BDay freq is deprecated:FutureWarning"
|
||||
)
|
||||
def test_freq(self, freq, base_date):
|
||||
rng = period_range(start=base_date, periods=10, freq=freq)
|
||||
exp = np.arange(10, dtype=np.int64)
|
||||
|
||||
tm.assert_numpy_array_equal(rng.asi8, exp)
|
||||
|
||||
|
||||
class TestPeriodIndexConversion:
|
||||
def test_tolist(self):
|
||||
index = period_range(freq="A", start="1/1/2001", end="12/1/2009")
|
||||
rs = index.tolist()
|
||||
for x in rs:
|
||||
assert isinstance(x, Period)
|
||||
|
||||
recon = PeriodIndex(rs)
|
||||
tm.assert_index_equal(index, recon)
|
Reference in New Issue
Block a user