venv
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,189 @@
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
Series,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
from pandas.tseries import offsets
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_asfreq(self):
|
||||
pi1 = period_range(freq="Y", 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("Y", "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("Y", "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("Y", "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("Y", "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("Y", "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("Y", "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)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq",
|
||||
[
|
||||
"2BMS",
|
||||
"2YS-MAR",
|
||||
"2bh",
|
||||
],
|
||||
)
|
||||
def test_pi_asfreq_not_supported_frequency(self, freq):
|
||||
# GH#55785
|
||||
msg = f"{freq[1:]} is not supported as period frequency"
|
||||
|
||||
pi = PeriodIndex(["2020-01-01", "2021-01-01"], freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
pi.asfreq(freq=freq)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq",
|
||||
[
|
||||
"2BME",
|
||||
"2YE-MAR",
|
||||
"2QE",
|
||||
],
|
||||
)
|
||||
def test_pi_asfreq_invalid_frequency(self, freq):
|
||||
# GH#55785
|
||||
msg = f"Invalid frequency: {freq}"
|
||||
|
||||
pi = PeriodIndex(["2020-01-01", "2021-01-01"], freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
pi.asfreq(freq=freq)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq",
|
||||
[
|
||||
offsets.MonthBegin(2),
|
||||
offsets.BusinessMonthEnd(2),
|
||||
],
|
||||
)
|
||||
def test_pi_asfreq_invalid_baseoffset(self, freq):
|
||||
# GH#56945
|
||||
msg = re.escape(f"{freq} is not supported as period frequency")
|
||||
|
||||
pi = PeriodIndex(["2020-01-01", "2021-01-01"], freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
pi.asfreq(freq=freq)
|
@ -0,0 +1,151 @@
|
||||
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", dtype=object)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
idx = period_range("1990", "2009", freq="Y", 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, unit):
|
||||
# GH#55958
|
||||
pi = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M")
|
||||
|
||||
exp = DatetimeIndex(
|
||||
["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern"
|
||||
).as_unit(unit)
|
||||
res = pi.astype(f"datetime64[{unit}, US/Eastern]")
|
||||
tm.assert_index_equal(res, exp)
|
||||
assert res.freq == exp.freq
|
@ -0,0 +1,41 @@
|
||||
import numpy as np
|
||||
|
||||
from pandas import PeriodIndex
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestFactorize:
|
||||
def test_factorize_period(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)
|
||||
|
||||
def test_factorize_period_nonmonotonic(self):
|
||||
idx2 = PeriodIndex(
|
||||
["2014-03", "2014-03", "2014-02", "2014-01", "2014-03", "2014-01"],
|
||||
freq="M",
|
||||
)
|
||||
exp_idx = PeriodIndex(["2014-01", "2014-02", "2014-03"], 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)
|
@ -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="Y")
|
||||
assert not index.is_full
|
||||
|
||||
index = PeriodIndex([2005, 2006, 2007], freq="Y")
|
||||
assert index.is_full
|
||||
|
||||
index = PeriodIndex([2005, 2005, 2007], freq="Y")
|
||||
assert not index.is_full
|
||||
|
||||
index = PeriodIndex([2005, 2005, 2006], freq="Y")
|
||||
assert index.is_full
|
||||
|
||||
index = PeriodIndex([2006, 2005, 2005], freq="Y")
|
||||
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="Y", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="Y", 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="Y", start="1/1/2001", end="12/1/2009")
|
||||
pi2 = period_range(freq="Y", 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="Y", 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,142 @@
|
||||
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="Y-DEC")
|
||||
result = idx.to_timestamp()
|
||||
expected = date_range("2017", periods=12, freq="YS-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)],
|
||||
dtype="M8[ns]",
|
||||
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: -2Y"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
result.to_period(freq="-2Y")
|
||||
|
||||
def test_to_timestamp_preserve_name(self):
|
||||
index = period_range(freq="Y", 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.from_fields(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"], dtype="M8[ns]", name="idx"
|
||||
)
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = idx.to_timestamp(how="E")
|
||||
expected = DatetimeIndex(
|
||||
["2011-02-28", "NaT", "2011-03-31"], dtype="M8[ns]", 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"], dtype="M8[ns]", 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", dtype="M8[ns]"
|
||||
)
|
||||
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"], dtype="M8[ns]", 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,691 @@
|
||||
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 TestPeriodIndexDisallowedFreqs:
|
||||
@pytest.mark.parametrize(
|
||||
"freq,freq_depr",
|
||||
[
|
||||
("2M", "2ME"),
|
||||
("2Q-MAR", "2QE-MAR"),
|
||||
("2Y-FEB", "2YE-FEB"),
|
||||
("2M", "2me"),
|
||||
("2Q-MAR", "2qe-MAR"),
|
||||
("2Y-FEB", "2yE-feb"),
|
||||
],
|
||||
)
|
||||
def test_period_index_offsets_frequency_error_message(self, freq, freq_depr):
|
||||
# GH#52064
|
||||
msg = f"for Period, please use '{freq[1:]}' instead of '{freq_depr[1:]}'"
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(["2020-01-01", "2020-01-02"], freq=freq_depr)
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2020-01-01", end="2020-01-02", freq=freq_depr)
|
||||
|
||||
@pytest.mark.parametrize("freq_depr", ["2SME", "2sme", "2CBME", "2BYE", "2Bye"])
|
||||
def test_period_index_frequency_invalid_freq(self, freq_depr):
|
||||
# GH#9586
|
||||
msg = f"Invalid frequency: {freq_depr[1:]}"
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range("2020-01", "2020-05", freq=freq_depr)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
PeriodIndex(["2020-01", "2020-05"], freq=freq_depr)
|
||||
|
||||
@pytest.mark.parametrize("freq", ["2BQE-SEP", "2BYE-MAR", "2BME"])
|
||||
def test_period_index_from_datetime_index_invalid_freq(self, freq):
|
||||
# GH#56899
|
||||
msg = f"Invalid frequency: {freq[1:]}"
|
||||
|
||||
rng = date_range("01-Jan-2012", periods=8, freq=freq)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
rng.to_period()
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
def test_from_ordinals(self):
|
||||
Period(ordinal=-1000, freq="Y")
|
||||
Period(ordinal=0, freq="Y")
|
||||
|
||||
msg = "The 'ordinal' keyword in PeriodIndex is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
idx1 = PeriodIndex(ordinal=[-1, 0, 1], freq="Y")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
idx2 = PeriodIndex(ordinal=np.array([-1, 0, 1]), freq="Y")
|
||||
tm.assert_index_equal(idx1, idx2)
|
||||
|
||||
alt1 = PeriodIndex.from_ordinals([-1, 0, 1], freq="Y")
|
||||
tm.assert_index_equal(alt1, idx1)
|
||||
|
||||
alt2 = PeriodIndex.from_ordinals(np.array([-1, 0, 1]), freq="Y")
|
||||
tm.assert_index_equal(alt2, idx2)
|
||||
|
||||
def test_keyword_mismatch(self):
|
||||
# GH#55961 we should get exactly one of data/ordinals/**fields
|
||||
per = Period("2016-01-01", "D")
|
||||
depr_msg1 = "The 'ordinal' keyword in PeriodIndex is deprecated"
|
||||
depr_msg2 = "Constructing PeriodIndex from fields is deprecated"
|
||||
|
||||
err_msg1 = "Cannot pass both data and ordinal"
|
||||
with pytest.raises(ValueError, match=err_msg1):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg1):
|
||||
PeriodIndex(data=[per], ordinal=[per.ordinal], freq=per.freq)
|
||||
|
||||
err_msg2 = "Cannot pass both data and fields"
|
||||
with pytest.raises(ValueError, match=err_msg2):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg2):
|
||||
PeriodIndex(data=[per], year=[per.year], freq=per.freq)
|
||||
|
||||
err_msg3 = "Cannot pass both ordinal and fields"
|
||||
with pytest.raises(ValueError, match=err_msg3):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg2):
|
||||
PeriodIndex(ordinal=[per.ordinal], year=[per.year], freq=per.freq)
|
||||
|
||||
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]
|
||||
|
||||
depr_msg = "Constructing PeriodIndex from fields is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
index = PeriodIndex(year=years, quarter=quarters, freq="Q-DEC")
|
||||
expected = period_range("1990Q3", "2009Q2", freq="Q-DEC")
|
||||
tm.assert_index_equal(index, expected)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
index2 = PeriodIndex(year=years, quarter=quarters, freq="2Q-DEC")
|
||||
tm.assert_numpy_array_equal(index.asi8, index2.asi8)
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
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):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
PeriodIndex(year=years, month=months, freq="M")
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
PeriodIndex(year=years, month=months, freq="2M")
|
||||
|
||||
years = [2007, 2007, 2007]
|
||||
months = [1, 2, 3]
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
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_nano(self):
|
||||
idx = period_range(
|
||||
start=Period(ordinal=1, freq="ns"),
|
||||
end=Period(ordinal=4, freq="ns"),
|
||||
freq="ns",
|
||||
)
|
||||
exp = PeriodIndex(
|
||||
[
|
||||
Period(ordinal=1, freq="ns"),
|
||||
Period(ordinal=2, freq="ns"),
|
||||
Period(ordinal=3, freq="ns"),
|
||||
Period(ordinal=4, freq="ns"),
|
||||
],
|
||||
freq="ns",
|
||||
)
|
||||
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)
|
||||
|
||||
msg = "Constructing PeriodIndex from fields is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
pindex = PeriodIndex(year=years, quarter=quarters)
|
||||
|
||||
tm.assert_index_equal(pindex.year, Index(years))
|
||||
tm.assert_index_equal(pindex.quarter, Index(quarters))
|
||||
|
||||
alt = PeriodIndex.from_fields(year=years, quarter=quarters)
|
||||
tm.assert_index_equal(alt, pindex)
|
||||
|
||||
def test_constructor_invalid_quarters(self):
|
||||
depr_msg = "Constructing PeriodIndex from fields is deprecated"
|
||||
msg = "Quarter must be 1 <= q <= 4"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
PeriodIndex(
|
||||
year=range(2000, 2004), quarter=list(range(4)), freq="Q-DEC"
|
||||
)
|
||||
|
||||
def test_period_range_fractional_period(self):
|
||||
msg = "Non-integer 'periods' in pd.date_range, pd.timedelta_range"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
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="30min")
|
||||
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="Y"))
|
||||
|
||||
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 == "ME"
|
||||
|
||||
result = PeriodIndex(idx, freq="2M")
|
||||
tm.assert_index_equal(result, idx.asfreq("2M"))
|
||||
assert result.freq == "2ME"
|
||||
|
||||
result = PeriodIndex(idx, freq=offsets.MonthEnd(2))
|
||||
tm.assert_index_equal(result, idx.asfreq("2M"))
|
||||
assert result.freq == "2ME"
|
||||
|
||||
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="ME")
|
||||
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 == "ME"
|
||||
|
||||
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)
|
||||
|
||||
@pytest.mark.parametrize("floats", [[1.1, 2.1], np.array([1.1, 2.1])])
|
||||
def test_constructor_floats(self, floats):
|
||||
msg = "PeriodIndex does not allow floating point in construction"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
PeriodIndex(floats)
|
||||
|
||||
def test_constructor_year_and_quarter(self):
|
||||
year = Series([2001, 2002, 2003])
|
||||
quarter = year - 2000
|
||||
msg = "Constructing PeriodIndex from fields is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
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_offset, freq_period",
|
||||
[
|
||||
("YE", "Y"),
|
||||
("ME", "M"),
|
||||
("D", "D"),
|
||||
("min", "min"),
|
||||
("s", "s"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("mult", [1, 2, 3, 4, 5])
|
||||
def test_constructor_freq_mult_dti_compat(self, mult, freq_offset, freq_period):
|
||||
freqstr_offset = str(mult) + freq_offset
|
||||
freqstr_period = str(mult) + freq_period
|
||||
pidx = period_range(start="2014-04-01", freq=freqstr_period, periods=10)
|
||||
expected = date_range(
|
||||
start="2014-04-01", freq=freqstr_offset, periods=10
|
||||
).to_period(freqstr_period)
|
||||
tm.assert_index_equal(pidx, expected)
|
||||
|
||||
@pytest.mark.parametrize("mult", [1, 2, 3, 4, 5])
|
||||
def test_constructor_freq_mult_dti_compat_month(self, mult):
|
||||
pidx = period_range(start="2014-04-01", freq=f"{mult}M", periods=10)
|
||||
expected = date_range(
|
||||
start="2014-04-01", freq=f"{mult}ME", periods=10
|
||||
).to_period(f"{mult}M")
|
||||
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_period_range_length(self):
|
||||
pi = period_range(freq="Y", 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
|
||||
|
||||
msg = "'w' is deprecated and will be removed in a future version."
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
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
|
||||
|
||||
def test_infer_freq_from_first_element(self):
|
||||
msg = "Period with BDay freq is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
start = Period("02-Apr-2005", "B")
|
||||
end_intv = Period("2005-05-01", "B")
|
||||
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
|
||||
|
||||
def test_mixed_freq_raises(self):
|
||||
# Mixed freq should fail
|
||||
msg = "Period with BDay freq is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
end_intv = Period("2005-05-01", "B")
|
||||
|
||||
msg = "'w' is deprecated and will be removed in a future version."
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
vals = [end_intv, Period("2006-12-31", "w")]
|
||||
msg = r"Input has different freq=W-SUN from PeriodIndex\(freq=B\)"
|
||||
depr_msg = r"PeriodDtype\[B\] is deprecated"
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
PeriodIndex(vals)
|
||||
vals = np.array(vals)
|
||||
with pytest.raises(IncompatibleFrequency, match=msg):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
PeriodIndex(vals)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq", ["M", "Q", "Y", "D", "B", "min", "s", "ms", "us", "ns", "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="Y")
|
||||
|
||||
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 TestSimpleNew:
|
||||
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_period_index_simple_new_disallows_floats(self, floats):
|
||||
with pytest.raises(AssertionError, match="<class "):
|
||||
PeriodIndex._simple_new(floats)
|
||||
|
||||
|
||||
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):
|
||||
pi = period_range("1/1/2000", periods=10)
|
||||
ser = Series(pi, dtype=PeriodDtype("D"))
|
||||
exp = Series(pi)
|
||||
tm.assert_series_equal(ser, exp)
|
@ -0,0 +1,350 @@
|
||||
from contextlib import nullcontext
|
||||
from datetime import (
|
||||
datetime,
|
||||
time,
|
||||
)
|
||||
import locale
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import pandas as pd
|
||||
from pandas import (
|
||||
PeriodIndex,
|
||||
Series,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
def get_local_am_pm():
|
||||
"""Return the AM and PM strings returned by strftime in current locale."""
|
||||
am_local = time(1).strftime("%p")
|
||||
pm_local = time(13).strftime("%p")
|
||||
return am_local, pm_local
|
||||
|
||||
|
||||
def test_get_values_for_csv():
|
||||
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._get_values_for_csv()
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
# No NaN values, so na_rep has no effect
|
||||
result = index._get_values_for_csv(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._get_values_for_csv(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._get_values_for_csv(na_rep="NaT")
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
expected = np.array(["2017-01-01", "pandas", "2017-01-03"], dtype=object)
|
||||
|
||||
result = index._get_values_for_csv(na_rep="pandas")
|
||||
tm.assert_numpy_array_equal(result, expected)
|
||||
|
||||
|
||||
class TestPeriodIndexRendering:
|
||||
def test_format_empty(self):
|
||||
# GH#35712
|
||||
empty_idx = PeriodIndex([], freq="Y")
|
||||
msg = r"PeriodIndex\.format is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert empty_idx.format() == []
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert empty_idx.format(name=True) == [""]
|
||||
|
||||
@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="Y")
|
||||
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[Y-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
|
||||
|
||||
# TODO: These are Series.__repr__ tests
|
||||
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="Y")
|
||||
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[Y-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="Y")
|
||||
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: Y-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
|
||||
|
||||
|
||||
class TestPeriodIndexFormat:
|
||||
def test_period_format_and_strftime_default(self):
|
||||
per = PeriodIndex([datetime(2003, 1, 1, 12), None], freq="h")
|
||||
|
||||
# Default formatting
|
||||
msg = "PeriodIndex.format is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format()
|
||||
assert formatted[0] == "2003-01-01 12:00" # default: minutes not shown
|
||||
assert formatted[1] == "NaT"
|
||||
# format is equivalent to strftime(None)...
|
||||
assert formatted[0] == per.strftime(None)[0]
|
||||
assert per.strftime(None)[1] is np.nan # ...except for NaTs
|
||||
|
||||
# Same test with nanoseconds freq
|
||||
per = pd.period_range("2003-01-01 12:01:01.123456789", periods=2, freq="ns")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format()
|
||||
assert (formatted == per.strftime(None)).all()
|
||||
assert formatted[0] == "2003-01-01 12:01:01.123456789"
|
||||
assert formatted[1] == "2003-01-01 12:01:01.123456790"
|
||||
|
||||
def test_period_custom(self):
|
||||
# GH#46252 custom formatting directives %l (ms) and %u (us)
|
||||
msg = "PeriodIndex.format is deprecated"
|
||||
|
||||
# 3 digits
|
||||
per = pd.period_range("2003-01-01 12:01:01.123", periods=2, freq="ms")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format(date_format="%y %I:%M:%S (ms=%l us=%u ns=%n)")
|
||||
assert formatted[0] == "03 12:01:01 (ms=123 us=123000 ns=123000000)"
|
||||
assert formatted[1] == "03 12:01:01 (ms=124 us=124000 ns=124000000)"
|
||||
|
||||
# 6 digits
|
||||
per = pd.period_range("2003-01-01 12:01:01.123456", periods=2, freq="us")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format(date_format="%y %I:%M:%S (ms=%l us=%u ns=%n)")
|
||||
assert formatted[0] == "03 12:01:01 (ms=123 us=123456 ns=123456000)"
|
||||
assert formatted[1] == "03 12:01:01 (ms=123 us=123457 ns=123457000)"
|
||||
|
||||
# 9 digits
|
||||
per = pd.period_range("2003-01-01 12:01:01.123456789", periods=2, freq="ns")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format(date_format="%y %I:%M:%S (ms=%l us=%u ns=%n)")
|
||||
assert formatted[0] == "03 12:01:01 (ms=123 us=123456 ns=123456789)"
|
||||
assert formatted[1] == "03 12:01:01 (ms=123 us=123456 ns=123456790)"
|
||||
|
||||
def test_period_tz(self):
|
||||
# Formatting periods created from a datetime with timezone.
|
||||
msg = r"PeriodIndex\.format is deprecated"
|
||||
# This timestamp is in 2013 in Europe/Paris but is 2012 in UTC
|
||||
dt = pd.to_datetime(["2013-01-01 00:00:00+01:00"], utc=True)
|
||||
|
||||
# Converting to a period looses the timezone information
|
||||
# Since tz is currently set as utc, we'll see 2012
|
||||
with tm.assert_produces_warning(UserWarning, match="will drop timezone"):
|
||||
per = dt.to_period(freq="h")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert per.format()[0] == "2012-12-31 23:00"
|
||||
|
||||
# If tz is currently set as paris before conversion, we'll see 2013
|
||||
dt = dt.tz_convert("Europe/Paris")
|
||||
with tm.assert_produces_warning(UserWarning, match="will drop timezone"):
|
||||
per = dt.to_period(freq="h")
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
assert per.format()[0] == "2013-01-01 00:00"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"locale_str",
|
||||
[
|
||||
pytest.param(None, id=str(locale.getlocale())),
|
||||
"it_IT.utf8",
|
||||
"it_IT", # Note: encoding will be 'ISO8859-1'
|
||||
"zh_CN.utf8",
|
||||
"zh_CN", # Note: encoding will be 'gb2312'
|
||||
],
|
||||
)
|
||||
def test_period_non_ascii_fmt(self, locale_str):
|
||||
# GH#46468 non-ascii char in input format string leads to wrong output
|
||||
|
||||
# Skip if locale cannot be set
|
||||
if locale_str is not None and not tm.can_set_locale(locale_str, locale.LC_ALL):
|
||||
pytest.skip(f"Skipping as locale '{locale_str}' cannot be set on host.")
|
||||
|
||||
# Change locale temporarily for this test.
|
||||
with tm.set_locale(locale_str, locale.LC_ALL) if locale_str else nullcontext():
|
||||
# Scalar
|
||||
per = pd.Period("2018-03-11 13:00", freq="h")
|
||||
assert per.strftime("%y é") == "18 é"
|
||||
|
||||
# Index
|
||||
per = pd.period_range("2003-01-01 01:00:00", periods=2, freq="12h")
|
||||
msg = "PeriodIndex.format is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format(date_format="%y é")
|
||||
assert formatted[0] == "03 é"
|
||||
assert formatted[1] == "03 é"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"locale_str",
|
||||
[
|
||||
pytest.param(None, id=str(locale.getlocale())),
|
||||
"it_IT.utf8",
|
||||
"it_IT", # Note: encoding will be 'ISO8859-1'
|
||||
"zh_CN.utf8",
|
||||
"zh_CN", # Note: encoding will be 'gb2312'
|
||||
],
|
||||
)
|
||||
def test_period_custom_locale_directive(self, locale_str):
|
||||
# GH#46319 locale-specific directive leads to non-utf8 c strftime char* result
|
||||
|
||||
# Skip if locale cannot be set
|
||||
if locale_str is not None and not tm.can_set_locale(locale_str, locale.LC_ALL):
|
||||
pytest.skip(f"Skipping as locale '{locale_str}' cannot be set on host.")
|
||||
|
||||
# Change locale temporarily for this test.
|
||||
with tm.set_locale(locale_str, locale.LC_ALL) if locale_str else nullcontext():
|
||||
# Get locale-specific reference
|
||||
am_local, pm_local = get_local_am_pm()
|
||||
|
||||
# Scalar
|
||||
per = pd.Period("2018-03-11 13:00", freq="h")
|
||||
assert per.strftime("%p") == pm_local
|
||||
|
||||
# Index
|
||||
per = pd.period_range("2003-01-01 01:00:00", periods=2, freq="12h")
|
||||
msg = "PeriodIndex.format is deprecated"
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
formatted = per.format(date_format="%y %I:%M:%S%p")
|
||||
assert formatted[0] == f"03 01:00:00{am_local}"
|
||||
assert formatted[1] == f"03 01:00:00{pm_local}"
|
@ -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="Y", periods=10)
|
||||
bad_period = Period("2012", "Y")
|
||||
with pytest.raises(KeyError, match=r"^Period\('2012', 'Y-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 (
|
||||
DataFrame,
|
||||
Index,
|
||||
PeriodIndex,
|
||||
date_range,
|
||||
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 = DataFrame(
|
||||
np.ones((3, 2)),
|
||||
index=date_range("2020-01-01", periods=3),
|
||||
columns=period_range("2020-01-01", periods=2),
|
||||
)
|
||||
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,198 @@
|
||||
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, warn_copy_on_write
|
||||
):
|
||||
# monotonic
|
||||
idx = PeriodIndex([2000, 2007, 2007, 2009, 2009], freq="Y-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)
|
||||
with tm.assert_cow_warning(warn_copy_on_write):
|
||||
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="Y-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=idx[:0], 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,231 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
Index,
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
Series,
|
||||
date_range,
|
||||
offsets,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodIndex:
|
||||
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)
|
||||
|
||||
@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="Y", 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="Y", 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("Y"))
|
||||
|
||||
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="Y-JUN")
|
||||
expected = PeriodIndex([2000, 2007, 2009], freq="Y-JUN")
|
||||
tm.assert_index_equal(idx.unique(), expected)
|
||||
assert idx.nunique() == 3
|
||||
|
||||
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="Y")
|
||||
result = index.map(lambda x: x.ordinal)
|
||||
exp = Index([x.ordinal for x in index])
|
||||
tm.assert_index_equal(result, exp)
|
||||
|
||||
|
||||
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,241 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from pandas import (
|
||||
NaT,
|
||||
Period,
|
||||
PeriodIndex,
|
||||
date_range,
|
||||
period_range,
|
||||
)
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestPeriodRangeKeywords:
|
||||
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")
|
||||
|
||||
def test_required_arguments2(self):
|
||||
start = Period("02-Apr-2005", "D")
|
||||
msg = (
|
||||
"Of the three parameters: start, end, and periods, exactly two "
|
||||
"must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start=start)
|
||||
|
||||
def test_required_arguments3(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()
|
||||
|
||||
def test_required_arguments_too_many(self):
|
||||
msg = (
|
||||
"Of the three parameters: start, end, and periods, "
|
||||
"exactly two must be specified"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2017Q1", end="2018Q1", periods=8, freq="Q")
|
||||
|
||||
def test_start_end_non_nat(self):
|
||||
# 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=NaT, end="2018Q1", freq="Q")
|
||||
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2017Q1", end=NaT)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
period_range(start="2017Q1", end=NaT, freq="Q")
|
||||
|
||||
def test_periods_requires_integer(self):
|
||||
# invalid periods param
|
||||
msg = "periods must be a number, got foo"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
period_range(start="2017Q1", periods="foo")
|
||||
|
||||
|
||||
class TestPeriodRange:
|
||||
@pytest.mark.parametrize(
|
||||
"freq_offset, freq_period",
|
||||
[
|
||||
("D", "D"),
|
||||
("W", "W"),
|
||||
("QE", "Q"),
|
||||
("YE", "Y"),
|
||||
],
|
||||
)
|
||||
def test_construction_from_string(self, freq_offset, freq_period):
|
||||
# non-empty
|
||||
expected = date_range(
|
||||
start="2017-01-01", periods=5, freq=freq_offset, name="foo"
|
||||
).to_period()
|
||||
start, end = str(expected[0]), str(expected[-1])
|
||||
|
||||
result = period_range(start=start, end=end, freq=freq_period, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=start, periods=5, freq=freq_period, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=5, freq=freq_period, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# empty
|
||||
expected = PeriodIndex([], freq=freq_period, name="foo")
|
||||
|
||||
result = period_range(start=start, periods=0, freq=freq_period, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=0, freq=freq_period, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=end, end=start, freq=freq_period, name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
def test_construction_from_string_monthly(self):
|
||||
# non-empty
|
||||
expected = date_range(
|
||||
start="2017-01-01", periods=5, freq="ME", name="foo"
|
||||
).to_period()
|
||||
start, end = str(expected[0]), str(expected[-1])
|
||||
|
||||
result = period_range(start=start, end=end, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=start, periods=5, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=5, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# empty
|
||||
expected = PeriodIndex([], freq="M", name="foo")
|
||||
|
||||
result = period_range(start=start, periods=0, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(end=end, periods=0, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
result = period_range(start=end, end=start, freq="M", 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="ME", name="foo"
|
||||
).to_period()
|
||||
result = period_range(start=start, end=end, freq="M", name="foo")
|
||||
tm.assert_index_equal(result, expected)
|
||||
|
||||
# downsampling
|
||||
start = Period("2017-1", freq="M")
|
||||
end = Period("2019-12", freq="M")
|
||||
expected = date_range(
|
||||
start="2017-01-31", end="2019-12-31", freq="QE", 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 = Period("2017Q1", freq="Q")
|
||||
end = 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_mismatched_start_end_freq_raises(self):
|
||||
depr_msg = "Period with BDay freq is deprecated"
|
||||
msg = "'w' is deprecated and will be removed in a future version."
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
end_w = Period("2006-12-31", "1w")
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
start_b = Period("02-Apr-2005", "B")
|
||||
end_b = Period("2005-05-01", "B")
|
||||
|
||||
msg = "start and end must have same freq"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
period_range(start=start_b, end=end_w)
|
||||
|
||||
# without mismatch we are OK
|
||||
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
|
||||
period_range(start=start_b, end=end_b)
|
||||
|
||||
|
||||
class TestPeriodRangeDisallowedFreqs:
|
||||
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")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"freq,freq_depr",
|
||||
[
|
||||
("2Y", "2A"),
|
||||
("2Y", "2a"),
|
||||
("2Y-AUG", "2A-AUG"),
|
||||
("2Y-AUG", "2A-aug"),
|
||||
],
|
||||
)
|
||||
def test_a_deprecated_from_time_series(self, freq, freq_depr):
|
||||
# GH#52536
|
||||
msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
|
||||
f"future version. Please use '{freq[1:]}' instead."
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
period_range(freq=freq_depr, start="1/1/2001", end="12/1/2009")
|
||||
|
||||
@pytest.mark.parametrize("freq_depr", ["2H", "2MIN", "2S", "2US", "2NS"])
|
||||
def test_uppercase_freq_deprecated_from_time_series(self, freq_depr):
|
||||
# GH#52536, GH#54939
|
||||
msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
|
||||
f"future version. Please use '{freq_depr.lower()[1:]}' instead."
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
period_range("2020-01-01 00:00:00 00:00", periods=2, freq=freq_depr)
|
||||
|
||||
@pytest.mark.parametrize("freq_depr", ["2m", "2q-sep", "2y", "2w"])
|
||||
def test_lowercase_freq_deprecated_from_time_series(self, freq_depr):
|
||||
# GH#52536, GH#54939
|
||||
msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a "
|
||||
f"future version. Please use '{freq_depr.upper()[1:]}' instead."
|
||||
|
||||
with tm.assert_produces_warning(FutureWarning, match=msg):
|
||||
period_range(freq=freq_depr, start="1/1/2001", end="12/1/2009")
|
@ -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", "Y"])
|
||||
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",
|
||||
[
|
||||
("Y", "year"),
|
||||
("Q", "quarter"),
|
||||
("M", "month"),
|
||||
("D", "day"),
|
||||
("h", "hour"),
|
||||
("min", "minute"),
|
||||
("s", "second"),
|
||||
("ms", "millisecond"),
|
||||
("us", "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="ME")
|
||||
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,363 @@
|
||||
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="min"
|
||||
)
|
||||
other5 = PeriodIndex(
|
||||
["2000-01-01 09:01", "2000-01-01 09:05", "2000-01-01 09:08"], freq="min"
|
||||
)
|
||||
expected5 = PeriodIndex(
|
||||
[
|
||||
"2000-01-01 09:01",
|
||||
"2000-01-01 09:03",
|
||||
"2000-01-01 09:05",
|
||||
"2000-01-01 09:08",
|
||||
],
|
||||
freq="min",
|
||||
)
|
||||
|
||||
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="Y", periods=5)
|
||||
other7 = period_range("1998-01-01", freq="Y", periods=8)
|
||||
expected7 = PeriodIndex(
|
||||
[
|
||||
"2003",
|
||||
"2004",
|
||||
"2005",
|
||||
"2006",
|
||||
"2007",
|
||||
"1998",
|
||||
"1999",
|
||||
"2000",
|
||||
"2001",
|
||||
"2002",
|
||||
],
|
||||
freq="Y",
|
||||
)
|
||||
|
||||
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 False:
|
||||
tm.assert_index_equal(result.sort_values(), index)
|
||||
else:
|
||||
tm.assert_index_equal(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 False:
|
||||
tm.assert_index_equal(result.sort_values(), index[10:-5])
|
||||
else:
|
||||
tm.assert_index_equal(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="min")
|
||||
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="min"
|
||||
)
|
||||
other5 = PeriodIndex(["2000-01-01 09:01", "2000-01-01 09:05"], freq="min")
|
||||
expected5 = PeriodIndex(["2000-01-01 09:03"], freq="min")
|
||||
|
||||
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="Y")
|
||||
other7 = period_range("1998-01-01", freq="Y", periods=8)
|
||||
expected7 = PeriodIndex(["2007", "2006"], freq="Y")
|
||||
|
||||
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"),
|
||||
("min", "1970-01-01"),
|
||||
("s", "1970-01-01"),
|
||||
("ms", "1970-01-01"),
|
||||
("us", "1970-01-01"),
|
||||
("ns", "1970-01-01"),
|
||||
("M", "1970-01"),
|
||||
("Y", 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="Y", 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