Skip to content

Commit dd84044

Browse files
BUG: Series construction with EA dtype and index but no data fails (#33846)
1 parent 14eda58 commit dd84044

File tree

8 files changed

+76
-3
lines changed

8 files changed

+76
-3
lines changed

doc/source/whatsnew/v1.1.0.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,8 @@ Sparse
752752
ExtensionArray
753753
^^^^^^^^^^^^^^
754754

755-
- Fixed bug where :meth:`Serires.value_counts` would raise on empty input of ``Int64`` dtype (:issue:`33317`)
755+
- Fixed bug where :meth:`Series.value_counts` would raise on empty input of ``Int64`` dtype (:issue:`33317`)
756+
- Fixed bug in :class:`Series` construction with EA dtype and index but no data or scalar data fails (:issue:`26469`)
756757
- Fixed bug that caused :meth:`Series.__repr__()` to crash for extension types whose elements are multidimensional arrays (:issue:`33770`).
757758

758759

pandas/core/construction.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,11 @@ def sanitize_array(
450450
subarr = _try_cast(arr, dtype, copy, raise_cast_failure)
451451
elif isinstance(data, abc.Set):
452452
raise TypeError("Set type is unordered")
453+
elif lib.is_scalar(data) and index is not None and dtype is not None:
454+
data = maybe_cast_to_datetime(data, dtype)
455+
if not lib.is_scalar(data):
456+
data = data[0]
457+
subarr = construct_1d_arraylike_from_scalar(data, len(index), dtype)
453458
else:
454459
subarr = _try_cast(data, dtype, copy, raise_cast_failure)
455460

@@ -516,7 +521,7 @@ def _try_cast(
516521
517522
Parameters
518523
----------
519-
arr : ndarray, list, tuple, iterator (catchall)
524+
arr : ndarray, scalar, list, tuple, iterator (catchall)
520525
Excludes: ExtensionArray, Series, Index.
521526
dtype : np.dtype, ExtensionDtype or None
522527
copy : bool

pandas/core/dtypes/cast.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,9 @@ def maybe_cast_to_datetime(value, dtype, errors: str = "raise"):
13841384
pass
13851385

13861386
# coerce datetimelike to object
1387-
elif is_datetime64_dtype(value) and not is_datetime64_dtype(dtype):
1387+
elif is_datetime64_dtype(
1388+
getattr(value, "dtype", None)
1389+
) and not is_datetime64_dtype(dtype):
13881390
if is_object_dtype(dtype):
13891391
if value.dtype != DT64NS_DTYPE:
13901392
value = value.astype(DT64NS_DTYPE)

pandas/tests/extension/arrow/test_bool.py

+14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import numpy as np
22
import pytest
33

4+
from pandas.compat import PY37
5+
46
import pandas as pd
57
import pandas._testing as tm
68
from pandas.tests.extension import base
@@ -55,6 +57,18 @@ def test_from_dtype(self, data):
5557
def test_from_sequence_from_cls(self, data):
5658
super().test_from_sequence_from_cls(data)
5759

60+
@pytest.mark.skipif(not PY37, reason="timeout on Linux py36_locale")
61+
@pytest.mark.xfail(reason="pa.NULL is not recognised as scalar, GH-33899")
62+
def test_series_constructor_no_data_with_index(self, dtype, na_value):
63+
# pyarrow.lib.ArrowInvalid: only handle 1-dimensional arrays
64+
super().test_series_constructor_no_data_with_index(dtype, na_value)
65+
66+
@pytest.mark.skipif(not PY37, reason="timeout on Linux py36_locale")
67+
@pytest.mark.xfail(reason="pa.NULL is not recognised as scalar, GH-33899")
68+
def test_series_constructor_scalar_na_with_index(self, dtype, na_value):
69+
# pyarrow.lib.ArrowInvalid: only handle 1-dimensional arrays
70+
super().test_series_constructor_scalar_na_with_index(dtype, na_value)
71+
5872

5973
class TestReduce(base.BaseNoReduceTests):
6074
def test_reduce_series_boolean(self):

pandas/tests/extension/base/constructors.py

+25
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ def test_series_constructor(self, data):
3333
assert result2.dtype == data.dtype
3434
assert isinstance(result2._mgr.blocks[0], ExtensionBlock)
3535

36+
def test_series_constructor_no_data_with_index(self, dtype, na_value):
37+
result = pd.Series(index=[1, 2, 3], dtype=dtype)
38+
expected = pd.Series([na_value] * 3, index=[1, 2, 3], dtype=dtype)
39+
self.assert_series_equal(result, expected)
40+
41+
# GH 33559 - empty index
42+
result = pd.Series(index=[], dtype=dtype)
43+
expected = pd.Series([], index=pd.Index([], dtype="object"), dtype=dtype)
44+
self.assert_series_equal(result, expected)
45+
46+
def test_series_constructor_scalar_na_with_index(self, dtype, na_value):
47+
result = pd.Series(na_value, index=[1, 2, 3], dtype=dtype)
48+
expected = pd.Series([na_value] * 3, index=[1, 2, 3], dtype=dtype)
49+
self.assert_series_equal(result, expected)
50+
51+
def test_series_constructor_scalar_with_index(self, data, dtype):
52+
scalar = data[0]
53+
result = pd.Series(scalar, index=[1, 2, 3], dtype=dtype)
54+
expected = pd.Series([scalar] * 3, index=[1, 2, 3], dtype=dtype)
55+
self.assert_series_equal(result, expected)
56+
57+
result = pd.Series(scalar, index=["foo"], dtype=dtype)
58+
expected = pd.Series([scalar], index=["foo"], dtype=dtype)
59+
self.assert_series_equal(result, expected)
60+
3661
@pytest.mark.parametrize("from_series", [True, False])
3762
def test_dataframe_constructor_from_dict(self, data, from_series):
3863
if from_series:

pandas/tests/extension/json/test_json.py

+15
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,21 @@ def test_from_dtype(self, data):
150150
# construct from our dtype & string dtype
151151
pass
152152

153+
@pytest.mark.xfail(reason="RecursionError, GH-33900")
154+
def test_series_constructor_no_data_with_index(self, dtype, na_value):
155+
# RecursionError: maximum recursion depth exceeded in comparison
156+
super().test_series_constructor_no_data_with_index(dtype, na_value)
157+
158+
@pytest.mark.xfail(reason="RecursionError, GH-33900")
159+
def test_series_constructor_scalar_na_with_index(self, dtype, na_value):
160+
# RecursionError: maximum recursion depth exceeded in comparison
161+
super().test_series_constructor_scalar_na_with_index(dtype, na_value)
162+
163+
@pytest.mark.xfail(reason="collection as scalar, GH-33901")
164+
def test_series_constructor_scalar_with_index(self, data, dtype):
165+
# TypeError: All values must be of type <class 'collections.abc.Mapping'>
166+
super().test_series_constructor_scalar_with_index(data, dtype)
167+
153168

154169
class TestReshaping(BaseJSON, base.BaseReshapingTests):
155170
@pytest.mark.skip(reason="Different definitions of NA")

pandas/tests/extension/test_numpy.py

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ def test_array_from_scalars(self, data):
151151
# ValueError: PandasArray must be 1-dimensional.
152152
super().test_array_from_scalars(data)
153153

154+
@skip_nested
155+
def test_series_constructor_scalar_with_index(self, data, dtype):
156+
# ValueError: Length of passed values is 1, index implies 3.
157+
super().test_series_constructor_scalar_with_index(data, dtype)
158+
154159

155160
class TestDtype(BaseNumPyTests, base.BaseDtypeTests):
156161
@pytest.mark.skip(reason="Incorrect expected.")

pandas/tests/series/test_constructors.py

+6
Original file line numberDiff line numberDiff line change
@@ -1444,3 +1444,9 @@ def test_constructor_datetime64(self):
14441444

14451445
series = Series(dates)
14461446
assert np.issubdtype(series.dtype, np.dtype("M8[ns]"))
1447+
1448+
def test_constructor_datetimelike_scalar_to_string_dtype(self):
1449+
# https://github.com/pandas-dev/pandas/pull/33846
1450+
result = Series("M", index=[1, 2, 3], dtype="string")
1451+
expected = pd.Series(["M", "M", "M"], index=[1, 2, 3], dtype="string")
1452+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)