123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- """
- Additional tests for PandasArray that aren't covered by
- the interface tests.
- """
- import numpy as np
- import pytest
- import pandas as pd
- import pandas._testing as tm
- from pandas.arrays import PandasArray
- from pandas.core.arrays.numpy_ import PandasDtype
- @pytest.fixture(
- params=[
- np.array(["a", "b"], dtype=object),
- np.array([0, 1], dtype=float),
- np.array([0, 1], dtype=int),
- np.array([0, 1 + 2j], dtype=complex),
- np.array([True, False], dtype=bool),
- np.array([0, 1], dtype="datetime64[ns]"),
- np.array([0, 1], dtype="timedelta64[ns]"),
- ]
- )
- def any_numpy_array(request):
- """
- Parametrized fixture for NumPy arrays with different dtypes.
- This excludes string and bytes.
- """
- return request.param
- # ----------------------------------------------------------------------------
- # PandasDtype
- @pytest.mark.parametrize(
- "dtype, expected",
- [
- ("bool", True),
- ("int", True),
- ("uint", True),
- ("float", True),
- ("complex", True),
- ("str", False),
- ("bytes", False),
- ("datetime64[ns]", False),
- ("object", False),
- ("void", False),
- ],
- )
- def test_is_numeric(dtype, expected):
- dtype = PandasDtype(dtype)
- assert dtype._is_numeric is expected
- @pytest.mark.parametrize(
- "dtype, expected",
- [
- ("bool", True),
- ("int", False),
- ("uint", False),
- ("float", False),
- ("complex", False),
- ("str", False),
- ("bytes", False),
- ("datetime64[ns]", False),
- ("object", False),
- ("void", False),
- ],
- )
- def test_is_boolean(dtype, expected):
- dtype = PandasDtype(dtype)
- assert dtype._is_boolean is expected
- def test_repr():
- dtype = PandasDtype(np.dtype("int64"))
- assert repr(dtype) == "PandasDtype('int64')"
- def test_constructor_from_string():
- result = PandasDtype.construct_from_string("int64")
- expected = PandasDtype(np.dtype("int64"))
- assert result == expected
- # ----------------------------------------------------------------------------
- # Construction
- def test_constructor_no_coercion():
- with pytest.raises(ValueError, match="NumPy array"):
- PandasArray([1, 2, 3])
- def test_series_constructor_with_copy():
- ndarray = np.array([1, 2, 3])
- ser = pd.Series(PandasArray(ndarray), copy=True)
- assert ser.values is not ndarray
- def test_series_constructor_with_astype():
- ndarray = np.array([1, 2, 3])
- result = pd.Series(PandasArray(ndarray), dtype="float64")
- expected = pd.Series([1.0, 2.0, 3.0], dtype="float64")
- tm.assert_series_equal(result, expected)
- def test_from_sequence_dtype():
- arr = np.array([1, 2, 3], dtype="int64")
- result = PandasArray._from_sequence(arr, dtype="uint64")
- expected = PandasArray(np.array([1, 2, 3], dtype="uint64"))
- tm.assert_extension_array_equal(result, expected)
- def test_constructor_copy():
- arr = np.array([0, 1])
- result = PandasArray(arr, copy=True)
- assert np.shares_memory(result._ndarray, arr) is False
- def test_constructor_with_data(any_numpy_array):
- nparr = any_numpy_array
- arr = PandasArray(nparr)
- assert arr.dtype.numpy_dtype == nparr.dtype
- # ----------------------------------------------------------------------------
- # Conversion
- def test_to_numpy():
- arr = PandasArray(np.array([1, 2, 3]))
- result = arr.to_numpy()
- assert result is arr._ndarray
- result = arr.to_numpy(copy=True)
- assert result is not arr._ndarray
- result = arr.to_numpy(dtype="f8")
- expected = np.array([1, 2, 3], dtype="f8")
- tm.assert_numpy_array_equal(result, expected)
- # ----------------------------------------------------------------------------
- # Setitem
- def test_setitem_series():
- ser = pd.Series([1, 2, 3])
- ser.array[0] = 10
- expected = pd.Series([10, 2, 3])
- tm.assert_series_equal(ser, expected)
- def test_setitem(any_numpy_array):
- nparr = any_numpy_array
- arr = PandasArray(nparr, copy=True)
- arr[0] = arr[1]
- nparr[0] = nparr[1]
- tm.assert_numpy_array_equal(arr.to_numpy(), nparr)
- # ----------------------------------------------------------------------------
- # Reductions
- def test_bad_reduce_raises():
- arr = np.array([1, 2, 3], dtype="int64")
- arr = PandasArray(arr)
- msg = "cannot perform not_a_method with type int"
- with pytest.raises(TypeError, match=msg):
- arr._reduce(msg)
- def test_validate_reduction_keyword_args():
- arr = PandasArray(np.array([1, 2, 3]))
- msg = "the 'keepdims' parameter is not supported .*all"
- with pytest.raises(ValueError, match=msg):
- arr.all(keepdims=True)
- # ----------------------------------------------------------------------------
- # Ops
- def test_ufunc():
- arr = PandasArray(np.array([-1.0, 0.0, 1.0]))
- result = np.abs(arr)
- expected = PandasArray(np.abs(arr._ndarray))
- tm.assert_extension_array_equal(result, expected)
- r1, r2 = np.divmod(arr, np.add(arr, 2))
- e1, e2 = np.divmod(arr._ndarray, np.add(arr._ndarray, 2))
- e1 = PandasArray(e1)
- e2 = PandasArray(e2)
- tm.assert_extension_array_equal(r1, e1)
- tm.assert_extension_array_equal(r2, e2)
- def test_basic_binop():
- # Just a basic smoke test. The EA interface tests exercise this
- # more thoroughly.
- x = PandasArray(np.array([1, 2, 3]))
- result = x + x
- expected = PandasArray(np.array([2, 4, 6]))
- tm.assert_extension_array_equal(result, expected)
- @pytest.mark.parametrize("dtype", [None, object])
- def test_setitem_object_typecode(dtype):
- arr = PandasArray(np.array(["a", "b", "c"], dtype=dtype))
- arr[0] = "t"
- expected = PandasArray(np.array(["t", "b", "c"], dtype=dtype))
- tm.assert_extension_array_equal(arr, expected)
- def test_setitem_no_coercion():
- # https://github.com/pandas-dev/pandas/issues/28150
- arr = PandasArray(np.array([1, 2, 3]))
- with pytest.raises(ValueError, match="int"):
- arr[0] = "a"
- # With a value that we do coerce, check that we coerce the value
- # and not the underlying array.
- arr[0] = 2.5
- assert isinstance(arr[0], (int, np.integer)), type(arr[0])
- def test_setitem_preserves_views():
- # GH#28150, see also extension test of the same name
- arr = PandasArray(np.array([1, 2, 3]))
- view1 = arr.view()
- view2 = arr[:]
- view3 = np.asarray(arr)
- arr[0] = 9
- assert view1[0] == 9
- assert view2[0] == 9
- assert view3[0] == 9
- arr[-1] = 2.5
- view1[-1] = 5
- assert arr[-1] == 5
|