| |
| |
| |
| from __future__ import annotations |
|
|
| from collections import abc |
| from datetime import timedelta |
| from decimal import Decimal |
| import operator |
|
|
| import numpy as np |
| import pytest |
|
|
| import pandas as pd |
| from pandas import ( |
| Index, |
| RangeIndex, |
| Series, |
| Timedelta, |
| TimedeltaIndex, |
| array, |
| date_range, |
| ) |
| import pandas._testing as tm |
| from pandas.core import ops |
| from pandas.core.computation import expressions as expr |
| from pandas.tests.arithmetic.common import ( |
| assert_invalid_addsub_type, |
| assert_invalid_comparison, |
| ) |
|
|
|
|
| @pytest.fixture(autouse=True, params=[0, 1000000], ids=["numexpr", "python"]) |
| def switch_numexpr_min_elements(request, monkeypatch): |
| with monkeypatch.context() as m: |
| m.setattr(expr, "_MIN_ELEMENTS", request.param) |
| yield request.param |
|
|
|
|
| @pytest.fixture(params=[Index, Series, tm.to_array]) |
| def box_pandas_1d_array(request): |
| """ |
| Fixture to test behavior for Index, Series and tm.to_array classes |
| """ |
| return request.param |
|
|
|
|
| @pytest.fixture( |
| params=[ |
| |
| Index(np.arange(5, dtype="float64")), |
| Index(np.arange(5, dtype="int64")), |
| Index(np.arange(5, dtype="uint64")), |
| RangeIndex(5), |
| ], |
| ids=lambda x: type(x).__name__, |
| ) |
| def numeric_idx(request): |
| """ |
| Several types of numeric-dtypes Index objects |
| """ |
| return request.param |
|
|
|
|
| @pytest.fixture( |
| params=[Index, Series, tm.to_array, np.array, list], ids=lambda x: x.__name__ |
| ) |
| def box_1d_array(request): |
| """ |
| Fixture to test behavior for Index, Series, tm.to_array, numpy Array and list |
| classes |
| """ |
| return request.param |
|
|
|
|
| def adjust_negative_zero(zero, expected): |
| """ |
| Helper to adjust the expected result if we are dividing by -0.0 |
| as opposed to 0.0 |
| """ |
| if np.signbit(np.array(zero)).any(): |
| |
| |
| assert np.signbit(np.array(zero)).all() |
|
|
| expected *= -1 |
|
|
| return expected |
|
|
|
|
| def compare_op(series, other, op): |
| left = np.abs(series) if op in (ops.rpow, operator.pow) else series |
| right = np.abs(other) if op in (ops.rpow, operator.pow) else other |
|
|
| cython_or_numpy = op(left, right) |
| python = left.combine(right, op) |
| if isinstance(other, Series) and not other.index.equals(series.index): |
| python.index = python.index._with_freq(None) |
| tm.assert_series_equal(cython_or_numpy, python) |
|
|
|
|
| |
| |
| |
| _ldtypes = ["i1", "i2", "i4", "i8", "u1", "u2", "u4", "u8", "f2", "f4", "f8"] |
| lefts: list[Index | Series] = [RangeIndex(10, 40, 10)] |
| lefts.extend([Series([10, 20, 30], dtype=dtype) for dtype in _ldtypes]) |
| lefts.extend([Index([10, 20, 30], dtype=dtype) for dtype in _ldtypes if dtype != "f2"]) |
|
|
| |
| |
|
|
|
|
| class TestNumericComparisons: |
| def test_operator_series_comparison_zerorank(self): |
| |
| result = np.float64(0) > Series([1, 2, 3]) |
| expected = 0.0 > Series([1, 2, 3]) |
| tm.assert_series_equal(result, expected) |
| result = Series([1, 2, 3]) < np.float64(0) |
| expected = Series([1, 2, 3]) < 0.0 |
| tm.assert_series_equal(result, expected) |
| result = np.array([0, 1, 2])[0] > Series([0, 1, 2]) |
| expected = 0.0 > Series([1, 2, 3]) |
| tm.assert_series_equal(result, expected) |
|
|
| def test_df_numeric_cmp_dt64_raises(self, box_with_array, fixed_now_ts): |
| |
| ts = fixed_now_ts |
| obj = np.array(range(5)) |
| obj = tm.box_expected(obj, box_with_array) |
|
|
| assert_invalid_comparison(obj, ts, box_with_array) |
|
|
| def test_compare_invalid(self): |
| |
| |
| a = Series(np.random.default_rng(2).standard_normal(5), name=0) |
| b = Series(np.random.default_rng(2).standard_normal(5)) |
| b.name = pd.Timestamp("2000-01-01") |
| tm.assert_series_equal(a / b, 1 / (b / a)) |
|
|
| def test_numeric_cmp_string_numexpr_path(self, box_with_array, monkeypatch): |
| |
| box = box_with_array |
| xbox = box if box is not Index else np.ndarray |
|
|
| obj = Series(np.random.default_rng(2).standard_normal(51)) |
| obj = tm.box_expected(obj, box, transpose=False) |
| with monkeypatch.context() as m: |
| m.setattr(expr, "_MIN_ELEMENTS", 50) |
| result = obj == "a" |
|
|
| expected = Series(np.zeros(51, dtype=bool)) |
| expected = tm.box_expected(expected, xbox, transpose=False) |
| tm.assert_equal(result, expected) |
|
|
| with monkeypatch.context() as m: |
| m.setattr(expr, "_MIN_ELEMENTS", 50) |
| result = obj != "a" |
| tm.assert_equal(result, ~expected) |
|
|
| msg = "Invalid comparison between dtype=float64 and str" |
| with pytest.raises(TypeError, match=msg): |
| obj < "a" |
|
|
|
|
| |
| |
|
|
|
|
| class TestNumericArraylikeArithmeticWithDatetimeLike: |
| @pytest.mark.parametrize("box_cls", [np.array, Index, Series]) |
| @pytest.mark.parametrize( |
| "left", lefts, ids=lambda x: type(x).__name__ + str(x.dtype) |
| ) |
| def test_mul_td64arr(self, left, box_cls): |
| |
| right = np.array([1, 2, 3], dtype="m8[s]") |
| right = box_cls(right) |
|
|
| expected = TimedeltaIndex(["10s", "40s", "90s"], dtype=right.dtype) |
|
|
| if isinstance(left, Series) or box_cls is Series: |
| expected = Series(expected) |
| assert expected.dtype == right.dtype |
|
|
| result = left * right |
| tm.assert_equal(result, expected) |
|
|
| result = right * left |
| tm.assert_equal(result, expected) |
|
|
| @pytest.mark.parametrize("box_cls", [np.array, Index, Series]) |
| @pytest.mark.parametrize( |
| "left", lefts, ids=lambda x: type(x).__name__ + str(x.dtype) |
| ) |
| def test_div_td64arr(self, left, box_cls): |
| |
| right = np.array([10, 40, 90], dtype="m8[s]") |
| right = box_cls(right) |
|
|
| expected = TimedeltaIndex(["1s", "2s", "3s"], dtype=right.dtype) |
| if isinstance(left, Series) or box_cls is Series: |
| expected = Series(expected) |
| assert expected.dtype == right.dtype |
|
|
| result = right / left |
| tm.assert_equal(result, expected) |
|
|
| result = right // left |
| tm.assert_equal(result, expected) |
|
|
| |
| msg = "ufunc '(true_)?divide' cannot use operands with types" |
| with pytest.raises(TypeError, match=msg): |
| left / right |
|
|
| msg = "ufunc 'floor_divide' cannot use operands with types" |
| with pytest.raises(TypeError, match=msg): |
| left // right |
|
|
| |
| |
| @pytest.mark.parametrize( |
| "scalar_td", |
| [ |
| Timedelta(days=1), |
| Timedelta(days=1).to_timedelta64(), |
| Timedelta(days=1).to_pytimedelta(), |
| Timedelta(days=1).to_timedelta64().astype("timedelta64[s]"), |
| Timedelta(days=1).to_timedelta64().astype("timedelta64[ms]"), |
| ], |
| ids=lambda x: type(x).__name__, |
| ) |
| def test_numeric_arr_mul_tdscalar(self, scalar_td, numeric_idx, box_with_array): |
| |
| box = box_with_array |
| index = numeric_idx |
| expected = TimedeltaIndex([Timedelta(days=n) for n in range(len(index))]) |
| if isinstance(scalar_td, np.timedelta64): |
| dtype = scalar_td.dtype |
| expected = expected.astype(dtype) |
| elif type(scalar_td) is timedelta: |
| expected = expected.astype("m8[us]") |
|
|
| index = tm.box_expected(index, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = index * scalar_td |
| tm.assert_equal(result, expected) |
|
|
| commute = scalar_td * index |
| tm.assert_equal(commute, expected) |
|
|
| @pytest.mark.parametrize( |
| "scalar_td", |
| [ |
| Timedelta(days=1), |
| Timedelta(days=1).to_timedelta64(), |
| Timedelta(days=1).to_pytimedelta(), |
| ], |
| ids=lambda x: type(x).__name__, |
| ) |
| @pytest.mark.parametrize("dtype", [np.int64, np.float64]) |
| def test_numeric_arr_mul_tdscalar_numexpr_path( |
| self, dtype, scalar_td, box_with_array |
| ): |
| |
| box = box_with_array |
|
|
| arr_i8 = np.arange(2 * 10**4).astype(np.int64, copy=False) |
| arr = arr_i8.astype(dtype, copy=False) |
| obj = tm.box_expected(arr, box, transpose=False) |
|
|
| expected = arr_i8.view("timedelta64[D]").astype("timedelta64[ns]") |
| if type(scalar_td) is timedelta: |
| expected = expected.astype("timedelta64[us]") |
|
|
| expected = tm.box_expected(expected, box, transpose=False) |
|
|
| result = obj * scalar_td |
| tm.assert_equal(result, expected) |
|
|
| result = scalar_td * obj |
| tm.assert_equal(result, expected) |
|
|
| def test_numeric_arr_rdiv_tdscalar(self, three_days, numeric_idx, box_with_array): |
| box = box_with_array |
|
|
| index = numeric_idx[1:3] |
|
|
| expected = TimedeltaIndex(["3 Days", "36 Hours"]) |
| if isinstance(three_days, np.timedelta64): |
| dtype = three_days.dtype |
| if dtype < np.dtype("m8[s]"): |
| |
| dtype = np.dtype("m8[s]") |
| expected = expected.astype(dtype) |
| elif type(three_days) is timedelta: |
| expected = expected.astype("m8[us]") |
| elif isinstance( |
| three_days, |
| (pd.offsets.Day, pd.offsets.Hour, pd.offsets.Minute, pd.offsets.Second), |
| ): |
| |
| expected = expected.astype("m8[s]") |
|
|
| index = tm.box_expected(index, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = three_days / index |
| tm.assert_equal(result, expected) |
|
|
| msg = "cannot use operands with types dtype" |
| with pytest.raises(TypeError, match=msg): |
| index / three_days |
|
|
| @pytest.mark.parametrize( |
| "other", |
| [ |
| Timedelta(hours=31), |
| Timedelta(hours=31).to_pytimedelta(), |
| Timedelta(hours=31).to_timedelta64(), |
| Timedelta(hours=31).to_timedelta64().astype("m8[h]"), |
| np.timedelta64("NaT"), |
| np.timedelta64("NaT", "D"), |
| pd.offsets.Minute(3), |
| pd.offsets.Second(0), |
| |
| |
| pd.Timestamp("2021-01-01", tz="Asia/Tokyo"), |
| pd.Timestamp("2021-01-01"), |
| pd.Timestamp("2021-01-01").to_pydatetime(), |
| pd.Timestamp("2021-01-01", tz="UTC").to_pydatetime(), |
| pd.Timestamp("2021-01-01").to_datetime64(), |
| np.datetime64("NaT", "ns"), |
| pd.NaT, |
| ], |
| ids=repr, |
| ) |
| def test_add_sub_datetimedeltalike_invalid( |
| self, numeric_idx, other, box_with_array |
| ): |
| box = box_with_array |
|
|
| left = tm.box_expected(numeric_idx, box) |
| msg = "|".join( |
| [ |
| "unsupported operand type", |
| "Addition/subtraction of integers and integer-arrays", |
| "Instead of adding/subtracting", |
| "cannot use operands with types dtype", |
| "Concatenation operation is not implemented for NumPy arrays", |
| "Cannot (add|subtract) NaT (to|from) ndarray", |
| |
| r"operand type\(s\) all returned NotImplemented from __array_ufunc__", |
| "can only perform ops with numeric values", |
| "cannot subtract DatetimeArray from ndarray", |
| |
| "Cannot add or subtract Timedelta from integers", |
| ] |
| ) |
| assert_invalid_addsub_type(left, other, msg) |
|
|
|
|
| |
| |
|
|
|
|
| class TestDivisionByZero: |
| def test_div_zero(self, zero, numeric_idx): |
| idx = numeric_idx |
|
|
| expected = Index([np.nan, np.inf, np.inf, np.inf, np.inf], dtype=np.float64) |
| |
| |
| expected2 = adjust_negative_zero(zero, expected) |
|
|
| result = idx / zero |
| tm.assert_index_equal(result, expected2) |
| ser_compat = Series(idx).astype("i8") / np.array(zero).astype("i8") |
| tm.assert_series_equal(ser_compat, Series(expected)) |
|
|
| def test_floordiv_zero(self, zero, numeric_idx): |
| idx = numeric_idx |
|
|
| expected = Index([np.nan, np.inf, np.inf, np.inf, np.inf], dtype=np.float64) |
| |
| |
| expected2 = adjust_negative_zero(zero, expected) |
|
|
| result = idx // zero |
| tm.assert_index_equal(result, expected2) |
| ser_compat = Series(idx).astype("i8") // np.array(zero).astype("i8") |
| tm.assert_series_equal(ser_compat, Series(expected)) |
|
|
| def test_mod_zero(self, zero, numeric_idx): |
| idx = numeric_idx |
|
|
| expected = Index([np.nan, np.nan, np.nan, np.nan, np.nan], dtype=np.float64) |
| result = idx % zero |
| tm.assert_index_equal(result, expected) |
| ser_compat = Series(idx).astype("i8") % np.array(zero).astype("i8") |
| tm.assert_series_equal(ser_compat, Series(result)) |
|
|
| def test_divmod_zero(self, zero, numeric_idx): |
| idx = numeric_idx |
|
|
| exleft = Index([np.nan, np.inf, np.inf, np.inf, np.inf], dtype=np.float64) |
| exright = Index([np.nan, np.nan, np.nan, np.nan, np.nan], dtype=np.float64) |
| exleft = adjust_negative_zero(zero, exleft) |
|
|
| result = divmod(idx, zero) |
| tm.assert_index_equal(result[0], exleft) |
| tm.assert_index_equal(result[1], exright) |
|
|
| @pytest.mark.parametrize("op", [operator.truediv, operator.floordiv]) |
| def test_div_negative_zero(self, zero, numeric_idx, op): |
| |
| if numeric_idx.dtype == np.uint64: |
| pytest.skip(f"Div by negative 0 not relevant for {numeric_idx.dtype}") |
| idx = numeric_idx - 3 |
|
|
| expected = Index([-np.inf, -np.inf, -np.inf, np.nan, np.inf], dtype=np.float64) |
| expected = adjust_negative_zero(zero, expected) |
|
|
| result = op(idx, zero) |
| tm.assert_index_equal(result, expected) |
|
|
| |
|
|
| @pytest.mark.parametrize("dtype1", [np.int64, np.float64, np.uint64]) |
| def test_ser_div_ser( |
| self, |
| switch_numexpr_min_elements, |
| dtype1, |
| any_real_numpy_dtype, |
| ): |
| |
| dtype2 = any_real_numpy_dtype |
|
|
| first = Series([3, 4, 5, 8], name="first").astype(dtype1) |
| second = Series([0, 0, 0, 3], name="second").astype(dtype2) |
|
|
| with np.errstate(all="ignore"): |
| expected = Series( |
| first.values.astype(np.float64) / second.values, |
| dtype="float64", |
| name=None, |
| ) |
| expected.iloc[0:3] = np.inf |
| if first.dtype == "int64" and second.dtype == "float32": |
| |
| |
| if expr.USE_NUMEXPR and switch_numexpr_min_elements == 0: |
| expected = expected.astype("float32") |
|
|
| result = first / second |
| tm.assert_series_equal(result, expected) |
| assert not result.equals(second / first) |
|
|
| @pytest.mark.parametrize("dtype1", [np.int64, np.float64, np.uint64]) |
| def test_ser_divmod_zero(self, dtype1, any_real_numpy_dtype): |
| |
| dtype2 = any_real_numpy_dtype |
| left = Series([1, 1]).astype(dtype1) |
| right = Series([0, 2]).astype(dtype2) |
|
|
| |
| |
| expected = left // right, left % right |
| expected = list(expected) |
| expected[0] = expected[0].astype(np.float64) |
| expected[0][0] = np.inf |
| result = divmod(left, right) |
|
|
| tm.assert_series_equal(result[0], expected[0]) |
| tm.assert_series_equal(result[1], expected[1]) |
|
|
| |
| result = divmod(left.values, right) |
| tm.assert_series_equal(result[0], expected[0]) |
| tm.assert_series_equal(result[1], expected[1]) |
|
|
| def test_ser_divmod_inf(self): |
| left = Series([np.inf, 1.0]) |
| right = Series([np.inf, 2.0]) |
|
|
| expected = left // right, left % right |
| result = divmod(left, right) |
|
|
| tm.assert_series_equal(result[0], expected[0]) |
| tm.assert_series_equal(result[1], expected[1]) |
|
|
| |
| result = divmod(left.values, right) |
| tm.assert_series_equal(result[0], expected[0]) |
| tm.assert_series_equal(result[1], expected[1]) |
|
|
| def test_rdiv_zero_compat(self): |
| |
| zero_array = np.array([0] * 5) |
| data = np.random.default_rng(2).standard_normal(5) |
| expected = Series([0.0] * 5) |
|
|
| result = zero_array / Series(data) |
| tm.assert_series_equal(result, expected) |
|
|
| result = Series(zero_array) / data |
| tm.assert_series_equal(result, expected) |
|
|
| result = Series(zero_array) / Series(data) |
| tm.assert_series_equal(result, expected) |
|
|
| def test_div_zero_inf_signs(self): |
| |
| ser = Series([-1, 0, 1], name="first") |
| expected = Series([-np.inf, np.nan, np.inf], name="first") |
|
|
| result = ser / 0 |
| tm.assert_series_equal(result, expected) |
|
|
| def test_rdiv_zero(self): |
| |
| ser = Series([-1, 0, 1], name="first") |
| expected = Series([0.0, np.nan, 0.0], name="first") |
|
|
| result = 0 / ser |
| tm.assert_series_equal(result, expected) |
|
|
| def test_floordiv_div(self): |
| |
| ser = Series([-1, 0, 1], name="first") |
|
|
| result = ser // 0 |
| expected = Series([-np.inf, np.nan, np.inf], name="first") |
| tm.assert_series_equal(result, expected) |
|
|
| def test_df_div_zero_df(self): |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
| result = df / df |
|
|
| first = Series([1.0, 1.0, 1.0, 1.0]) |
| second = Series([np.nan, np.nan, np.nan, 1]) |
| expected = pd.DataFrame({"first": first, "second": second}) |
| tm.assert_frame_equal(result, expected) |
|
|
| def test_df_div_zero_array(self): |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
|
|
| first = Series([1.0, 1.0, 1.0, 1.0]) |
| second = Series([np.nan, np.nan, np.nan, 1]) |
| expected = pd.DataFrame({"first": first, "second": second}) |
|
|
| with np.errstate(all="ignore"): |
| arr = df.values.astype("float") / df.values |
| result = pd.DataFrame(arr, index=df.index, columns=df.columns) |
| tm.assert_frame_equal(result, expected) |
|
|
| def test_df_div_zero_int(self): |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
|
|
| result = df / 0 |
| expected = pd.DataFrame(np.inf, index=df.index, columns=df.columns) |
| expected.iloc[0:3, 1] = np.nan |
| tm.assert_frame_equal(result, expected) |
|
|
| |
| with np.errstate(all="ignore"): |
| arr = df.values.astype("float64") / 0 |
| result2 = pd.DataFrame(arr, index=df.index, columns=df.columns) |
| tm.assert_frame_equal(result2, expected) |
|
|
| def test_df_div_zero_series_does_not_commute(self): |
| |
| df = pd.DataFrame(np.random.default_rng(2).standard_normal((10, 5))) |
| ser = df[0] |
| res = ser / df |
| res2 = df / ser |
| assert not res.fillna(0).equals(res2.fillna(0)) |
|
|
| |
| |
|
|
| def test_df_mod_zero_df(self, using_array_manager): |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
| |
| first = Series([0, 0, 0, 0]) |
| if not using_array_manager: |
| |
| |
| |
| first = first.astype("float64") |
| second = Series([np.nan, np.nan, np.nan, 0]) |
| expected = pd.DataFrame({"first": first, "second": second}) |
| result = df % df |
| tm.assert_frame_equal(result, expected) |
|
|
| |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}, copy=False) |
| first = Series([0, 0, 0, 0], dtype="int64") |
| second = Series([np.nan, np.nan, np.nan, 0]) |
| expected = pd.DataFrame({"first": first, "second": second}) |
| result = df % df |
| tm.assert_frame_equal(result, expected) |
|
|
| def test_df_mod_zero_array(self): |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
|
|
| |
| |
| first = Series([0, 0, 0, 0], dtype="float64") |
| second = Series([np.nan, np.nan, np.nan, 0]) |
| expected = pd.DataFrame({"first": first, "second": second}) |
|
|
| |
| with np.errstate(all="ignore"): |
| arr = df.values % df.values |
| result2 = pd.DataFrame(arr, index=df.index, columns=df.columns, dtype="float64") |
| result2.iloc[0:3, 1] = np.nan |
| tm.assert_frame_equal(result2, expected) |
|
|
| def test_df_mod_zero_int(self): |
| |
| df = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
|
|
| result = df % 0 |
| expected = pd.DataFrame(np.nan, index=df.index, columns=df.columns) |
| tm.assert_frame_equal(result, expected) |
|
|
| |
| with np.errstate(all="ignore"): |
| arr = df.values.astype("float64") % 0 |
| result2 = pd.DataFrame(arr, index=df.index, columns=df.columns) |
| tm.assert_frame_equal(result2, expected) |
|
|
| def test_df_mod_zero_series_does_not_commute(self): |
| |
| |
| df = pd.DataFrame(np.random.default_rng(2).standard_normal((10, 5))) |
| ser = df[0] |
| res = ser % df |
| res2 = df % ser |
| assert not res.fillna(0).equals(res2.fillna(0)) |
|
|
|
|
| class TestMultiplicationDivision: |
| |
| |
|
|
| def test_divide_decimal(self, box_with_array): |
| |
| box = box_with_array |
| ser = Series([Decimal(10)]) |
| expected = Series([Decimal(5)]) |
|
|
| ser = tm.box_expected(ser, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = ser / Decimal(2) |
|
|
| tm.assert_equal(result, expected) |
|
|
| result = ser // Decimal(2) |
| tm.assert_equal(result, expected) |
|
|
| def test_div_equiv_binop(self): |
| |
| |
| |
| first = Series([1, 0], name="first") |
| second = Series([-0.01, -0.02], name="second") |
| expected = Series([-0.01, -np.inf]) |
|
|
| result = second.div(first) |
| tm.assert_series_equal(result, expected, check_names=False) |
|
|
| result = second / first |
| tm.assert_series_equal(result, expected) |
|
|
| def test_div_int(self, numeric_idx): |
| idx = numeric_idx |
| result = idx / 1 |
| expected = idx.astype("float64") |
| tm.assert_index_equal(result, expected) |
|
|
| result = idx / 2 |
| expected = Index(idx.values / 2) |
| tm.assert_index_equal(result, expected) |
|
|
| @pytest.mark.parametrize("op", [operator.mul, ops.rmul, operator.floordiv]) |
| def test_mul_int_identity(self, op, numeric_idx, box_with_array): |
| idx = numeric_idx |
| idx = tm.box_expected(idx, box_with_array) |
|
|
| result = op(idx, 1) |
| tm.assert_equal(result, idx) |
|
|
| def test_mul_int_array(self, numeric_idx): |
| idx = numeric_idx |
| didx = idx * idx |
|
|
| result = idx * np.array(5, dtype="int64") |
| tm.assert_index_equal(result, idx * 5) |
|
|
| arr_dtype = "uint64" if idx.dtype == np.uint64 else "int64" |
| result = idx * np.arange(5, dtype=arr_dtype) |
| tm.assert_index_equal(result, didx) |
|
|
| def test_mul_int_series(self, numeric_idx): |
| idx = numeric_idx |
| didx = idx * idx |
|
|
| arr_dtype = "uint64" if idx.dtype == np.uint64 else "int64" |
| result = idx * Series(np.arange(5, dtype=arr_dtype)) |
| tm.assert_series_equal(result, Series(didx)) |
|
|
| def test_mul_float_series(self, numeric_idx): |
| idx = numeric_idx |
| rng5 = np.arange(5, dtype="float64") |
|
|
| result = idx * Series(rng5 + 0.1) |
| expected = Series(rng5 * (rng5 + 0.1)) |
| tm.assert_series_equal(result, expected) |
|
|
| def test_mul_index(self, numeric_idx): |
| idx = numeric_idx |
|
|
| result = idx * idx |
| tm.assert_index_equal(result, idx**2) |
|
|
| def test_mul_datelike_raises(self, numeric_idx): |
| idx = numeric_idx |
| msg = "cannot perform __rmul__ with this index type" |
| with pytest.raises(TypeError, match=msg): |
| idx * date_range("20130101", periods=5) |
|
|
| def test_mul_size_mismatch_raises(self, numeric_idx): |
| idx = numeric_idx |
| msg = "operands could not be broadcast together" |
| with pytest.raises(ValueError, match=msg): |
| idx * idx[0:3] |
| with pytest.raises(ValueError, match=msg): |
| idx * np.array([1, 2]) |
|
|
| @pytest.mark.parametrize("op", [operator.pow, ops.rpow]) |
| def test_pow_float(self, op, numeric_idx, box_with_array): |
| |
| box = box_with_array |
| idx = numeric_idx |
| expected = Index(op(idx.values, 2.0)) |
|
|
| idx = tm.box_expected(idx, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = op(idx, 2.0) |
| tm.assert_equal(result, expected) |
|
|
| def test_modulo(self, numeric_idx, box_with_array): |
| |
| box = box_with_array |
| idx = numeric_idx |
| expected = Index(idx.values % 2) |
|
|
| idx = tm.box_expected(idx, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = idx % 2 |
| tm.assert_equal(result, expected) |
|
|
| def test_divmod_scalar(self, numeric_idx): |
| idx = numeric_idx |
|
|
| result = divmod(idx, 2) |
| with np.errstate(all="ignore"): |
| div, mod = divmod(idx.values, 2) |
|
|
| expected = Index(div), Index(mod) |
| for r, e in zip(result, expected): |
| tm.assert_index_equal(r, e) |
|
|
| def test_divmod_ndarray(self, numeric_idx): |
| idx = numeric_idx |
| other = np.ones(idx.values.shape, dtype=idx.values.dtype) * 2 |
|
|
| result = divmod(idx, other) |
| with np.errstate(all="ignore"): |
| div, mod = divmod(idx.values, other) |
|
|
| expected = Index(div), Index(mod) |
| for r, e in zip(result, expected): |
| tm.assert_index_equal(r, e) |
|
|
| def test_divmod_series(self, numeric_idx): |
| idx = numeric_idx |
| other = np.ones(idx.values.shape, dtype=idx.values.dtype) * 2 |
|
|
| result = divmod(idx, Series(other)) |
| with np.errstate(all="ignore"): |
| div, mod = divmod(idx.values, other) |
|
|
| expected = Series(div), Series(mod) |
| for r, e in zip(result, expected): |
| tm.assert_series_equal(r, e) |
|
|
| @pytest.mark.parametrize("other", [np.nan, 7, -23, 2.718, -3.14, np.inf]) |
| def test_ops_np_scalar(self, other): |
| vals = np.random.default_rng(2).standard_normal((5, 3)) |
| f = lambda x: pd.DataFrame( |
| x, index=list("ABCDE"), columns=["jim", "joe", "jolie"] |
| ) |
|
|
| df = f(vals) |
|
|
| tm.assert_frame_equal(df / np.array(other), f(vals / other)) |
| tm.assert_frame_equal(np.array(other) * df, f(vals * other)) |
| tm.assert_frame_equal(df + np.array(other), f(vals + other)) |
| tm.assert_frame_equal(np.array(other) - df, f(other - vals)) |
|
|
| |
| def test_operators_frame(self): |
| |
| ts = Series( |
| np.arange(10, dtype=np.float64), |
| index=date_range("2020-01-01", periods=10), |
| name="ts", |
| ) |
| ts.name = "ts" |
|
|
| df = pd.DataFrame({"A": ts}) |
|
|
| tm.assert_series_equal(ts + ts, ts + df["A"], check_names=False) |
| tm.assert_series_equal(ts**ts, ts ** df["A"], check_names=False) |
| tm.assert_series_equal(ts < ts, ts < df["A"], check_names=False) |
| tm.assert_series_equal(ts / ts, ts / df["A"], check_names=False) |
|
|
| |
| |
| def test_modulo2(self): |
| with np.errstate(all="ignore"): |
| |
| p = pd.DataFrame({"first": [3, 4, 5, 8], "second": [0, 0, 0, 3]}) |
| result = p["first"] % p["second"] |
| expected = Series(p["first"].values % p["second"].values, dtype="float64") |
| expected.iloc[0:3] = np.nan |
| tm.assert_series_equal(result, expected) |
|
|
| result = p["first"] % 0 |
| expected = Series(np.nan, index=p.index, name="first") |
| tm.assert_series_equal(result, expected) |
|
|
| p = p.astype("float64") |
| result = p["first"] % p["second"] |
| expected = Series(p["first"].values % p["second"].values) |
| tm.assert_series_equal(result, expected) |
|
|
| p = p.astype("float64") |
| result = p["first"] % p["second"] |
| result2 = p["second"] % p["first"] |
| assert not result.equals(result2) |
|
|
| def test_modulo_zero_int(self): |
| |
| with np.errstate(all="ignore"): |
| s = Series([0, 1]) |
|
|
| result = s % 0 |
| expected = Series([np.nan, np.nan]) |
| tm.assert_series_equal(result, expected) |
|
|
| result = 0 % s |
| expected = Series([np.nan, 0.0]) |
| tm.assert_series_equal(result, expected) |
|
|
|
|
| class TestAdditionSubtraction: |
| |
| |
|
|
| @pytest.mark.parametrize( |
| "first, second, expected", |
| [ |
| ( |
| Series([1, 2, 3], index=list("ABC"), name="x"), |
| Series([2, 2, 2], index=list("ABD"), name="x"), |
| Series([3.0, 4.0, np.nan, np.nan], index=list("ABCD"), name="x"), |
| ), |
| ( |
| Series([1, 2, 3], index=list("ABC"), name="x"), |
| Series([2, 2, 2, 2], index=list("ABCD"), name="x"), |
| Series([3, 4, 5, np.nan], index=list("ABCD"), name="x"), |
| ), |
| ], |
| ) |
| def test_add_series(self, first, second, expected): |
| |
| tm.assert_series_equal(first + second, expected) |
| tm.assert_series_equal(second + first, expected) |
|
|
| @pytest.mark.parametrize( |
| "first, second, expected", |
| [ |
| ( |
| pd.DataFrame({"x": [1, 2, 3]}, index=list("ABC")), |
| pd.DataFrame({"x": [2, 2, 2]}, index=list("ABD")), |
| pd.DataFrame({"x": [3.0, 4.0, np.nan, np.nan]}, index=list("ABCD")), |
| ), |
| ( |
| pd.DataFrame({"x": [1, 2, 3]}, index=list("ABC")), |
| pd.DataFrame({"x": [2, 2, 2, 2]}, index=list("ABCD")), |
| pd.DataFrame({"x": [3, 4, 5, np.nan]}, index=list("ABCD")), |
| ), |
| ], |
| ) |
| def test_add_frames(self, first, second, expected): |
| |
| tm.assert_frame_equal(first + second, expected) |
| tm.assert_frame_equal(second + first, expected) |
|
|
| |
| def test_series_frame_radd_bug(self, fixed_now_ts): |
| |
| vals = Series([str(i) for i in range(5)]) |
| result = "foo_" + vals |
| expected = vals.map(lambda x: "foo_" + x) |
| tm.assert_series_equal(result, expected) |
|
|
| frame = pd.DataFrame({"vals": vals}) |
| result = "foo_" + frame |
| expected = pd.DataFrame({"vals": vals.map(lambda x: "foo_" + x)}) |
| tm.assert_frame_equal(result, expected) |
|
|
| ts = Series( |
| np.arange(10, dtype=np.float64), |
| index=date_range("2020-01-01", periods=10), |
| name="ts", |
| ) |
|
|
| |
| fix_now = fixed_now_ts.to_pydatetime() |
| msg = "|".join( |
| [ |
| "unsupported operand type", |
| |
| "Concatenation operation", |
| ] |
| ) |
| with pytest.raises(TypeError, match=msg): |
| fix_now + ts |
|
|
| with pytest.raises(TypeError, match=msg): |
| ts + fix_now |
|
|
| |
| def test_datetime64_with_index(self): |
| |
| ser = Series(np.random.default_rng(2).standard_normal(5)) |
| expected = ser - ser.index.to_series() |
| result = ser - ser.index |
| tm.assert_series_equal(result, expected) |
|
|
| |
| |
| ser = Series( |
| date_range("20130101", periods=5), |
| index=date_range("20130101", periods=5), |
| ) |
| expected = ser - ser.index.to_series() |
| result = ser - ser.index |
| tm.assert_series_equal(result, expected) |
|
|
| msg = "cannot subtract PeriodArray from DatetimeArray" |
| with pytest.raises(TypeError, match=msg): |
| |
| result = ser - ser.index.to_period() |
|
|
| df = pd.DataFrame( |
| np.random.default_rng(2).standard_normal((5, 2)), |
| index=date_range("20130101", periods=5), |
| ) |
| df["date"] = pd.Timestamp("20130102") |
| df["expected"] = df["date"] - df.index.to_series() |
| df["result"] = df["date"] - df.index |
| tm.assert_series_equal(df["result"], df["expected"], check_names=False) |
|
|
| |
| def test_frame_operators(self, float_frame): |
| frame = float_frame |
|
|
| garbage = np.random.default_rng(2).random(4) |
| colSeries = Series(garbage, index=np.array(frame.columns)) |
|
|
| idSum = frame + frame |
| seriesSum = frame + colSeries |
|
|
| for col, series in idSum.items(): |
| for idx, val in series.items(): |
| origVal = frame[col][idx] * 2 |
| if not np.isnan(val): |
| assert val == origVal |
| else: |
| assert np.isnan(origVal) |
|
|
| for col, series in seriesSum.items(): |
| for idx, val in series.items(): |
| origVal = frame[col][idx] + colSeries[col] |
| if not np.isnan(val): |
| assert val == origVal |
| else: |
| assert np.isnan(origVal) |
|
|
| def test_frame_operators_col_align(self, float_frame): |
| frame2 = pd.DataFrame(float_frame, columns=["D", "C", "B", "A"]) |
| added = frame2 + frame2 |
| expected = frame2 * 2 |
| tm.assert_frame_equal(added, expected) |
|
|
| def test_frame_operators_none_to_nan(self): |
| df = pd.DataFrame({"a": ["a", None, "b"]}) |
| tm.assert_frame_equal(df + df, pd.DataFrame({"a": ["aa", np.nan, "bb"]})) |
|
|
| @pytest.mark.parametrize("dtype", ("float", "int64")) |
| def test_frame_operators_empty_like(self, dtype): |
| |
| frames = [ |
| pd.DataFrame(dtype=dtype), |
| pd.DataFrame(columns=["A"], dtype=dtype), |
| pd.DataFrame(index=[0], dtype=dtype), |
| ] |
| for df in frames: |
| assert (df + df).equals(df) |
| tm.assert_frame_equal(df + df, df) |
|
|
| @pytest.mark.parametrize( |
| "func", |
| [lambda x: x * 2, lambda x: x[::2], lambda x: 5], |
| ids=["multiply", "slice", "constant"], |
| ) |
| def test_series_operators_arithmetic(self, all_arithmetic_functions, func): |
| op = all_arithmetic_functions |
| series = Series( |
| np.arange(10, dtype=np.float64), |
| index=date_range("2020-01-01", periods=10), |
| name="ts", |
| ) |
| other = func(series) |
| compare_op(series, other, op) |
|
|
| @pytest.mark.parametrize( |
| "func", [lambda x: x + 1, lambda x: 5], ids=["add", "constant"] |
| ) |
| def test_series_operators_compare(self, comparison_op, func): |
| op = comparison_op |
| series = Series( |
| np.arange(10, dtype=np.float64), |
| index=date_range("2020-01-01", periods=10), |
| name="ts", |
| ) |
| other = func(series) |
| compare_op(series, other, op) |
|
|
| @pytest.mark.parametrize( |
| "func", |
| [lambda x: x * 2, lambda x: x[::2], lambda x: 5], |
| ids=["multiply", "slice", "constant"], |
| ) |
| def test_divmod(self, func): |
| series = Series( |
| np.arange(10, dtype=np.float64), |
| index=date_range("2020-01-01", periods=10), |
| name="ts", |
| ) |
| other = func(series) |
| results = divmod(series, other) |
| if isinstance(other, abc.Iterable) and len(series) != len(other): |
| |
| |
| other_np = [] |
| for n in other: |
| other_np.append(n) |
| other_np.append(np.nan) |
| else: |
| other_np = other |
| other_np = np.asarray(other_np) |
| with np.errstate(all="ignore"): |
| expecteds = divmod(series.values, np.asarray(other_np)) |
|
|
| for result, expected in zip(results, expecteds): |
| |
| tm.assert_almost_equal(np.asarray(result), expected) |
|
|
| assert result.name == series.name |
| tm.assert_index_equal(result.index, series.index._with_freq(None)) |
|
|
| def test_series_divmod_zero(self): |
| |
| |
| |
| |
| |
| |
| |
| tser = Series( |
| np.arange(1, 11, dtype=np.float64), |
| index=date_range("2020-01-01", periods=10), |
| name="ts", |
| ) |
| other = tser * 0 |
|
|
| result = divmod(tser, other) |
| exp1 = Series([np.inf] * len(tser), index=tser.index, name="ts") |
| exp2 = Series([np.nan] * len(tser), index=tser.index, name="ts") |
| tm.assert_series_equal(result[0], exp1) |
| tm.assert_series_equal(result[1], exp2) |
|
|
|
|
| class TestUFuncCompat: |
| |
| @pytest.mark.parametrize("holder", [Index, RangeIndex, Series]) |
| @pytest.mark.parametrize("dtype", [np.int64, np.uint64, np.float64]) |
| def test_ufunc_compat(self, holder, dtype): |
| box = Series if holder is Series else Index |
|
|
| if holder is RangeIndex: |
| if dtype != np.int64: |
| pytest.skip(f"dtype {dtype} not relevant for RangeIndex") |
| idx = RangeIndex(0, 5, name="foo") |
| else: |
| idx = holder(np.arange(5, dtype=dtype), name="foo") |
| result = np.sin(idx) |
| expected = box(np.sin(np.arange(5, dtype=dtype)), name="foo") |
| tm.assert_equal(result, expected) |
|
|
| |
| @pytest.mark.parametrize("holder", [Index, Series]) |
| @pytest.mark.parametrize("dtype", [np.int64, np.uint64, np.float64]) |
| def test_ufunc_coercions(self, holder, dtype): |
| idx = holder([1, 2, 3, 4, 5], dtype=dtype, name="x") |
| box = Series if holder is Series else Index |
|
|
| result = np.sqrt(idx) |
| assert result.dtype == "f8" and isinstance(result, box) |
| exp = Index(np.sqrt(np.array([1, 2, 3, 4, 5], dtype=np.float64)), name="x") |
| exp = tm.box_expected(exp, box) |
| tm.assert_equal(result, exp) |
|
|
| result = np.divide(idx, 2.0) |
| assert result.dtype == "f8" and isinstance(result, box) |
| exp = Index([0.5, 1.0, 1.5, 2.0, 2.5], dtype=np.float64, name="x") |
| exp = tm.box_expected(exp, box) |
| tm.assert_equal(result, exp) |
|
|
| |
| result = idx + 2.0 |
| assert result.dtype == "f8" and isinstance(result, box) |
| exp = Index([3.0, 4.0, 5.0, 6.0, 7.0], dtype=np.float64, name="x") |
| exp = tm.box_expected(exp, box) |
| tm.assert_equal(result, exp) |
|
|
| result = idx - 2.0 |
| assert result.dtype == "f8" and isinstance(result, box) |
| exp = Index([-1.0, 0.0, 1.0, 2.0, 3.0], dtype=np.float64, name="x") |
| exp = tm.box_expected(exp, box) |
| tm.assert_equal(result, exp) |
|
|
| result = idx * 1.0 |
| assert result.dtype == "f8" and isinstance(result, box) |
| exp = Index([1.0, 2.0, 3.0, 4.0, 5.0], dtype=np.float64, name="x") |
| exp = tm.box_expected(exp, box) |
| tm.assert_equal(result, exp) |
|
|
| result = idx / 2.0 |
| assert result.dtype == "f8" and isinstance(result, box) |
| exp = Index([0.5, 1.0, 1.5, 2.0, 2.5], dtype=np.float64, name="x") |
| exp = tm.box_expected(exp, box) |
| tm.assert_equal(result, exp) |
|
|
| |
| @pytest.mark.parametrize("holder", [Index, Series]) |
| @pytest.mark.parametrize("dtype", [np.int64, np.uint64, np.float64]) |
| def test_ufunc_multiple_return_values(self, holder, dtype): |
| obj = holder([1, 2, 3], dtype=dtype, name="x") |
| box = Series if holder is Series else Index |
|
|
| result = np.modf(obj) |
| assert isinstance(result, tuple) |
| exp1 = Index([0.0, 0.0, 0.0], dtype=np.float64, name="x") |
| exp2 = Index([1.0, 2.0, 3.0], dtype=np.float64, name="x") |
| tm.assert_equal(result[0], tm.box_expected(exp1, box)) |
| tm.assert_equal(result[1], tm.box_expected(exp2, box)) |
|
|
| def test_ufunc_at(self): |
| s = Series([0, 1, 2], index=[1, 2, 3], name="x") |
| np.add.at(s, [0, 2], 10) |
| expected = Series([10, 1, 12], index=[1, 2, 3], name="x") |
| tm.assert_series_equal(s, expected) |
|
|
|
|
| class TestObjectDtypeEquivalence: |
| |
|
|
| @pytest.mark.parametrize("dtype", [None, object]) |
| def test_numarr_with_dtype_add_nan(self, dtype, box_with_array): |
| box = box_with_array |
| ser = Series([1, 2, 3], dtype=dtype) |
| expected = Series([np.nan, np.nan, np.nan], dtype=dtype) |
|
|
| ser = tm.box_expected(ser, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = np.nan + ser |
| tm.assert_equal(result, expected) |
|
|
| result = ser + np.nan |
| tm.assert_equal(result, expected) |
|
|
| @pytest.mark.parametrize("dtype", [None, object]) |
| def test_numarr_with_dtype_add_int(self, dtype, box_with_array): |
| box = box_with_array |
| ser = Series([1, 2, 3], dtype=dtype) |
| expected = Series([2, 3, 4], dtype=dtype) |
|
|
| ser = tm.box_expected(ser, box) |
| expected = tm.box_expected(expected, box) |
|
|
| result = 1 + ser |
| tm.assert_equal(result, expected) |
|
|
| result = ser + 1 |
| tm.assert_equal(result, expected) |
|
|
| |
| @pytest.mark.parametrize( |
| "op", |
| [operator.add, operator.sub, operator.mul, operator.truediv, operator.floordiv], |
| ) |
| def test_operators_reverse_object(self, op): |
| |
| arr = Series( |
| np.random.default_rng(2).standard_normal(10), |
| index=np.arange(10), |
| dtype=object, |
| ) |
|
|
| result = op(1.0, arr) |
| expected = op(1.0, arr.astype(float)) |
| tm.assert_series_equal(result.astype(float), expected) |
|
|
|
|
| class TestNumericArithmeticUnsorted: |
| |
| |
| @pytest.mark.parametrize( |
| "op", |
| [ |
| operator.add, |
| operator.sub, |
| operator.mul, |
| operator.floordiv, |
| operator.truediv, |
| ], |
| ) |
| @pytest.mark.parametrize( |
| "idx1", |
| [ |
| RangeIndex(0, 10, 1), |
| RangeIndex(0, 20, 2), |
| RangeIndex(-10, 10, 2), |
| RangeIndex(5, -5, -1), |
| ], |
| ) |
| @pytest.mark.parametrize( |
| "idx2", |
| [ |
| RangeIndex(0, 10, 1), |
| RangeIndex(0, 20, 2), |
| RangeIndex(-10, 10, 2), |
| RangeIndex(5, -5, -1), |
| ], |
| ) |
| def test_binops_index(self, op, idx1, idx2): |
| idx1 = idx1._rename("foo") |
| idx2 = idx2._rename("bar") |
| result = op(idx1, idx2) |
| expected = op(Index(idx1.to_numpy()), Index(idx2.to_numpy())) |
| tm.assert_index_equal(result, expected, exact="equiv") |
|
|
| @pytest.mark.parametrize( |
| "op", |
| [ |
| operator.add, |
| operator.sub, |
| operator.mul, |
| operator.floordiv, |
| operator.truediv, |
| ], |
| ) |
| @pytest.mark.parametrize( |
| "idx", |
| [ |
| RangeIndex(0, 10, 1), |
| RangeIndex(0, 20, 2), |
| RangeIndex(-10, 10, 2), |
| RangeIndex(5, -5, -1), |
| ], |
| ) |
| @pytest.mark.parametrize("scalar", [-1, 1, 2]) |
| def test_binops_index_scalar(self, op, idx, scalar): |
| result = op(idx, scalar) |
| expected = op(Index(idx.to_numpy()), scalar) |
| tm.assert_index_equal(result, expected, exact="equiv") |
|
|
| @pytest.mark.parametrize("idx1", [RangeIndex(0, 10, 1), RangeIndex(0, 20, 2)]) |
| @pytest.mark.parametrize("idx2", [RangeIndex(0, 10, 1), RangeIndex(0, 20, 2)]) |
| def test_binops_index_pow(self, idx1, idx2): |
| |
| |
| idx1 = idx1._rename("foo") |
| idx2 = idx2._rename("bar") |
| result = pow(idx1, idx2) |
| expected = pow(Index(idx1.to_numpy()), Index(idx2.to_numpy())) |
| tm.assert_index_equal(result, expected, exact="equiv") |
|
|
| @pytest.mark.parametrize("idx", [RangeIndex(0, 10, 1), RangeIndex(0, 20, 2)]) |
| @pytest.mark.parametrize("scalar", [1, 2]) |
| def test_binops_index_scalar_pow(self, idx, scalar): |
| |
| |
| result = pow(idx, scalar) |
| expected = pow(Index(idx.to_numpy()), scalar) |
| tm.assert_index_equal(result, expected, exact="equiv") |
|
|
| |
| @pytest.mark.parametrize( |
| "op", |
| [ |
| operator.add, |
| operator.sub, |
| operator.mul, |
| operator.floordiv, |
| operator.truediv, |
| operator.pow, |
| operator.mod, |
| ], |
| ) |
| def test_arithmetic_with_frame_or_series(self, op): |
| |
| |
| index = RangeIndex(5) |
| other = Series(np.random.default_rng(2).standard_normal(5)) |
|
|
| expected = op(Series(index), other) |
| result = op(index, other) |
| tm.assert_series_equal(result, expected) |
|
|
| other = pd.DataFrame(np.random.default_rng(2).standard_normal((2, 5))) |
| expected = op(pd.DataFrame([index, index]), other) |
| result = op(index, other) |
| tm.assert_frame_equal(result, expected) |
|
|
| def test_numeric_compat2(self): |
| |
| |
|
|
| idx = RangeIndex(0, 10, 2) |
|
|
| result = idx * 2 |
| expected = RangeIndex(0, 20, 4) |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| result = idx + 2 |
| expected = RangeIndex(2, 12, 2) |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| result = idx - 2 |
| expected = RangeIndex(-2, 8, 2) |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| result = idx / 2 |
| expected = RangeIndex(0, 5, 1).astype("float64") |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| result = idx / 4 |
| expected = RangeIndex(0, 10, 2) / 4 |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| result = idx // 1 |
| expected = idx |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| |
| result = idx * idx |
| expected = Index(idx.values * idx.values) |
| tm.assert_index_equal(result, expected, exact=True) |
|
|
| |
| idx = RangeIndex(0, 1000, 2) |
| result = idx**2 |
| expected = Index(idx._values) ** 2 |
| tm.assert_index_equal(Index(result.values), expected, exact=True) |
|
|
| @pytest.mark.parametrize( |
| "idx, div, expected", |
| [ |
| |
| (RangeIndex(0, 1000, 2), 2, RangeIndex(0, 500, 1)), |
| (RangeIndex(-99, -201, -3), -3, RangeIndex(33, 67, 1)), |
| ( |
| RangeIndex(0, 1000, 1), |
| 2, |
| Index(RangeIndex(0, 1000, 1)._values) // 2, |
| ), |
| ( |
| RangeIndex(0, 100, 1), |
| 2.0, |
| Index(RangeIndex(0, 100, 1)._values) // 2.0, |
| ), |
| (RangeIndex(0), 50, RangeIndex(0)), |
| (RangeIndex(2, 4, 2), 3, RangeIndex(0, 1, 1)), |
| (RangeIndex(-5, -10, -6), 4, RangeIndex(-2, -1, 1)), |
| (RangeIndex(-100, -200, 3), 2, RangeIndex(0)), |
| ], |
| ) |
| def test_numeric_compat2_floordiv(self, idx, div, expected): |
| |
| tm.assert_index_equal(idx // div, expected, exact=True) |
|
|
| @pytest.mark.parametrize("dtype", [np.int64, np.float64]) |
| @pytest.mark.parametrize("delta", [1, 0, -1]) |
| def test_addsub_arithmetic(self, dtype, delta): |
| |
| delta = dtype(delta) |
| index = Index([10, 11, 12], dtype=dtype) |
| result = index + delta |
| expected = Index(index.values + delta, dtype=dtype) |
| tm.assert_index_equal(result, expected) |
|
|
| |
| result = index - delta |
| expected = Index(index.values - delta, dtype=dtype) |
| tm.assert_index_equal(result, expected) |
|
|
| tm.assert_index_equal(index + index, 2 * index) |
| tm.assert_index_equal(index - index, 0 * index) |
| assert not (index - index).empty |
|
|
| def test_pow_nan_with_zero(self, box_with_array): |
| left = Index([np.nan, np.nan, np.nan]) |
| right = Index([0, 0, 0]) |
| expected = Index([1.0, 1.0, 1.0]) |
|
|
| left = tm.box_expected(left, box_with_array) |
| right = tm.box_expected(right, box_with_array) |
| expected = tm.box_expected(expected, box_with_array) |
|
|
| result = left**right |
| tm.assert_equal(result, expected) |
|
|
|
|
| def test_fill_value_inf_masking(): |
| |
| df = pd.DataFrame({"A": [0, 1, 2], "B": [1.1, None, 1.1]}) |
|
|
| other = pd.DataFrame({"A": [1.1, 1.2, 1.3]}, index=[0, 2, 3]) |
|
|
| result = df.rfloordiv(other, fill_value=1) |
|
|
| expected = pd.DataFrame( |
| {"A": [np.inf, 1.0, 0.0, 1.0], "B": [0.0, np.nan, 0.0, np.nan]} |
| ) |
| tm.assert_frame_equal(result, expected) |
|
|
|
|
| def test_dataframe_div_silenced(): |
| |
| pdf1 = pd.DataFrame( |
| { |
| "A": np.arange(10), |
| "B": [np.nan, 1, 2, 3, 4] * 2, |
| "C": [np.nan] * 10, |
| "D": np.arange(10), |
| }, |
| index=list("abcdefghij"), |
| columns=list("ABCD"), |
| ) |
| pdf2 = pd.DataFrame( |
| np.random.default_rng(2).standard_normal((10, 4)), |
| index=list("abcdefghjk"), |
| columns=list("ABCX"), |
| ) |
| with tm.assert_produces_warning(None): |
| pdf1.div(pdf2, fill_value=0) |
|
|
|
|
| @pytest.mark.parametrize( |
| "data, expected_data", |
| [([0, 1, 2], [0, 2, 4])], |
| ) |
| def test_integer_array_add_list_like( |
| box_pandas_1d_array, box_1d_array, data, expected_data |
| ): |
| |
| arr = array(data, dtype="Int64") |
| container = box_pandas_1d_array(arr) |
| left = container + box_1d_array(data) |
| right = box_1d_array(data) + container |
|
|
| if Series in [box_1d_array, box_pandas_1d_array]: |
| cls = Series |
| elif Index in [box_1d_array, box_pandas_1d_array]: |
| cls = Index |
| else: |
| cls = array |
|
|
| expected = cls(expected_data, dtype="Int64") |
|
|
| tm.assert_equal(left, expected) |
| tm.assert_equal(right, expected) |
|
|
|
|
| def test_sub_multiindex_swapped_levels(): |
| |
| df = pd.DataFrame( |
| {"a": np.random.default_rng(2).standard_normal(6)}, |
| index=pd.MultiIndex.from_product( |
| [["a", "b"], [0, 1, 2]], names=["levA", "levB"] |
| ), |
| ) |
| df2 = df.copy() |
| df2.index = df2.index.swaplevel(0, 1) |
| result = df - df2 |
| expected = pd.DataFrame([0.0] * 6, columns=["a"], index=df.index) |
| tm.assert_frame_equal(result, expected) |
|
|
|
|
| @pytest.mark.parametrize("power", [1, 2, 5]) |
| @pytest.mark.parametrize("string_size", [0, 1, 2, 5]) |
| def test_empty_str_comparison(power, string_size): |
| |
| a = np.array(range(10**power)) |
| right = pd.DataFrame(a, dtype=np.int64) |
| left = " " * string_size |
|
|
| result = right == left |
| expected = pd.DataFrame(np.zeros(right.shape, dtype=bool)) |
| tm.assert_frame_equal(result, expected) |
|
|
|
|
| def test_series_add_sub_with_UInt64(): |
| |
| series1 = Series([1, 2, 3]) |
| series2 = Series([2, 1, 3], dtype="UInt64") |
|
|
| result = series1 + series2 |
| expected = Series([3, 3, 6], dtype="Float64") |
| tm.assert_series_equal(result, expected) |
|
|
| result = series1 - series2 |
| expected = Series([-1, 1, 0], dtype="Float64") |
| tm.assert_series_equal(result, expected) |
|
|