Skip to content

Commit 10498a8

Browse files
committed
BUG: raise on empty-string conversion to pyarrow float (#66834)
Empty CSV fields with keep_default_na=False stored IEEE NaN in double[pyarrow] instead of raising like numpy float64.
1 parent 9492eb3 commit 10498a8

3 files changed

Lines changed: 18 additions & 16 deletions

File tree

doc/source/whatsnew/v3.1.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ Missing
649649
- Bug in :meth:`DataFrame.fillna` with a dict value raising ``RecursionError`` when columns are a :class:`MultiIndex` with duplicate entries (:issue:`53498`)
650650
- Bug in :meth:`DataFrame.interpolate` and :meth:`Series.interpolate` with ``method`` in ``"index"``, ``"values"`` or ``"time"`` raising when the index had an :class:`ArrowDtype` timestamp or duration dtype; these now match the equivalent :class:`DatetimeIndex` or :class:`TimedeltaIndex` (:issue:`66338`)
651651
- Bug in :meth:`Series.combine_first` crashing when Series names are :class:`Timestamp` objects (:issue:`65333`)
652-
- Bug in :class:`ArrowExtensionArray` where empty strings converted to a floating PyArrow dtype stored IEEE ``NaN`` instead of null, so :meth:`Series.fillna` did not fill them (e.g. empty CSV fields with ``dtype="double[pyarrow]"`` and ``keep_default_na=False``)
652+
- Bug in :class:`ArrowExtensionArray` where converting empty strings to a floating PyArrow dtype stored IEEE ``NaN`` instead of raising like numpy ``float64`` (e.g. empty CSV fields with ``dtype="double[pyarrow]"`` and ``keep_default_na=False``) (:issue:`66834`)
653653

654654
MultiIndex
655655
^^^^^^^^^^

pandas/core/arrays/arrow/array.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -514,12 +514,12 @@ def _from_sequence_of_strings(
514514
scalars = strings.cast(pa_type)
515515
else:
516516
mask = isna(strings)
517-
if (
518-
is_nan_na()
519-
and isinstance(scalars, np.ndarray)
520-
and np.issubdtype(scalars.dtype, np.floating)
521-
):
522-
mask = np.asarray(mask, dtype=np.bool_) | np.isnan(scalars)
517+
# to_numeric("") yields IEEE NaN without raising. Match numpy
518+
# float64: an empty string that was not treated as NA is invalid.
519+
arr = np.asarray(strings, dtype=object)
520+
unmasked_empty = (arr == "") & ~np.asarray(mask, dtype=np.bool_)
521+
if unmasked_empty.any():
522+
raise ValueError("could not convert string to float: ''")
523523
if mask is not None:
524524
scalars = pa.array(scalars, mask=mask, type=pa_type)
525525

pandas/tests/extension/test_arrow.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,18 +3562,20 @@ def test_from_sequence_of_strings_boolean():
35623562
ArrowExtensionArray._from_sequence_of_strings(strings, dtype=dtype)
35633563

35643564

3565-
def test_from_sequence_of_strings_empty_string_float(using_nan_is_na):
3565+
def test_from_sequence_of_strings_empty_string_float():
3566+
# GH#66834 match numpy float64: empty string is not a valid float
35663567
strings = ["1.5", "", "2.0"]
35673568
dtype = ArrowDtype(pa.float64())
3569+
with pytest.raises(ValueError, match="could not convert string to float"):
3570+
ArrowExtensionArray._from_sequence_of_strings(strings, dtype=dtype)
3571+
3572+
3573+
def test_from_sequence_of_strings_none_float():
3574+
strings = ["1.5", None, "2.0"]
3575+
dtype = ArrowDtype(pa.float64())
35683576
result = ArrowExtensionArray._from_sequence_of_strings(strings, dtype=dtype)
3569-
if using_nan_is_na:
3570-
expected = ArrowExtensionArray(pa.array([1.5, None, 2.0], type=pa.float64()))
3571-
tm.assert_extension_array_equal(result, expected)
3572-
filled = pd.Series(result, dtype=dtype).fillna(0)
3573-
tm.assert_series_equal(filled, pd.Series([1.5, 0.0, 2.0], dtype=dtype))
3574-
else:
3575-
assert not result.isna().any()
3576-
assert np.isnan(result.to_numpy(dtype="float64")[1])
3577+
expected = ArrowExtensionArray(pa.array([1.5, None, 2.0], type=pa.float64()))
3578+
tm.assert_extension_array_equal(result, expected)
35773579

35783580

35793581
def test_concat_empty_arrow_backed_series(dtype):

0 commit comments

Comments
 (0)