Skip to content

Commit 1bff9e1

Browse files
author
Matt Roeschke
committed
Merge branch 'master' into feature/generalized_window_operations
2 parents de88a55 + 7264788 commit 1bff9e1

File tree

19 files changed

+454
-485
lines changed

19 files changed

+454
-485
lines changed

doc/source/whatsnew/v1.0.0.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ Indexing
184184
- Bug in :meth:`DataFrame.explode` would duplicate frame in the presence of duplicates in the index (:issue:`28010`)
185185
- Bug in reindexing a :meth:`PeriodIndex` with another type of index that contained a `Period` (:issue:`28323`) (:issue:`28337`)
186186
- Fix assignment of column via `.loc` with numpy non-ns datetime type (:issue:`27395`)
187+
- Bug in :meth:`Float64Index.astype` where ``np.inf`` was not handled properly when casting to an integer dtype (:issue:`28475`)
187188

188189
Missing
189190
^^^^^^^
@@ -240,7 +241,7 @@ Sparse
240241
ExtensionArray
241242
^^^^^^^^^^^^^^
242243

243-
-
244+
- Bug in :class:`arrays.PandasArray` when setting a scalar string (:issue:`28118`, :issue:`28150`).
244245
-
245246

246247

pandas/_libs/testing.pyx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,9 @@ cpdef assert_almost_equal(a, b,
143143
from pandas.util.testing import assert_attr_equal
144144
assert_attr_equal('dtype', a, b, obj=obj)
145145

146-
try:
147-
if array_equivalent(a, b, strict_nan=True):
148-
return True
149-
except:
150-
pass
146+
if array_equivalent(a, b, strict_nan=True):
147+
return True
148+
151149
else:
152150
na, nb = len(a), len(b)
153151

pandas/core/arrays/numpy_.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,8 @@ def __setitem__(self, key, value):
235235
if not lib.is_scalar(value):
236236
value = np.asarray(value)
237237

238-
values = self._ndarray
239-
t = np.result_type(value, values)
240-
if t != self._ndarray.dtype:
241-
values = values.astype(t, casting="safe")
242-
values[key] = value
243-
self._dtype = PandasDtype(t)
244-
self._ndarray = values
245-
else:
246-
self._ndarray[key] = value
238+
value = np.asarray(value, dtype=self._ndarray.dtype)
239+
self._ndarray[key] = value
247240

248241
def __len__(self) -> int:
249242
return len(self._ndarray)

pandas/core/dtypes/missing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ def array_equivalent(left, right, strict_nan=False):
445445
if not isinstance(right_value, float) or not np.isnan(right_value):
446446
return False
447447
else:
448-
if left_value != right_value:
448+
if np.any(left_value != right_value):
449449
return False
450450
return True
451451

pandas/core/indexes/base.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def __new__(
452452
elif hasattr(data, "__array__"):
453453
return Index(np.asarray(data), dtype=dtype, copy=copy, name=name, **kwargs)
454454
elif data is None or is_scalar(data):
455-
cls._scalar_data_error(data)
455+
raise cls._scalar_data_error(data)
456456
else:
457457
if tupleize_cols and is_list_like(data):
458458
# GH21470: convert iterable to list before determining if empty
@@ -4020,7 +4020,9 @@ def _try_convert_to_int_index(cls, data, copy, name, dtype):
40204020

40214021
@classmethod
40224022
def _scalar_data_error(cls, data):
4023-
raise TypeError(
4023+
# We return the TypeError so that we can raise it from the constructor
4024+
# in order to keep mypy happy
4025+
return TypeError(
40244026
"{0}(...) must be called with a collection of some "
40254027
"kind, {1} was passed".format(cls.__name__, repr(data))
40264028
)
@@ -4048,7 +4050,7 @@ def _coerce_to_ndarray(cls, data):
40484050

40494051
if not isinstance(data, (np.ndarray, Index)):
40504052
if data is None or is_scalar(data):
4051-
cls._scalar_data_error(data)
4053+
raise cls._scalar_data_error(data)
40524054

40534055
# other iterable of some kind
40544056
if not isinstance(data, (ABCSeries, list, tuple)):

pandas/core/indexes/category.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def __new__(
194194
# if data is None, then categories must be provided
195195
if is_scalar(data):
196196
if data is not None or categories is None:
197-
cls._scalar_data_error(data)
197+
raise cls._scalar_data_error(data)
198198
data = []
199199

200200
data = cls._create_categorical(data, dtype=dtype)

pandas/core/indexes/numeric.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pandas._libs import index as libindex
66
from pandas.util._decorators import Appender, cache_readonly
77

8+
from pandas.core.dtypes.cast import astype_nansafe
89
from pandas.core.dtypes.common import (
910
is_bool,
1011
is_bool_dtype,
@@ -367,12 +368,11 @@ def astype(self, dtype, copy=True):
367368
"values are required for conversion"
368369
).format(dtype=dtype)
369370
raise TypeError(msg)
370-
elif (
371-
is_integer_dtype(dtype) and not is_extension_array_dtype(dtype)
372-
) and self.hasnans:
371+
elif is_integer_dtype(dtype) and not is_extension_array_dtype(dtype):
373372
# TODO(jreback); this can change once we have an EA Index type
374373
# GH 13149
375-
raise ValueError("Cannot convert NA to integer")
374+
arr = astype_nansafe(self.values, dtype=dtype)
375+
return Int64Index(arr)
376376
return super().astype(dtype, copy=copy)
377377

378378
@Appender(_index_shared_docs["_convert_scalar_indexer"])

pandas/tests/arithmetic/test_datetime64.py

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,6 @@ def assert_invalid_comparison(left, right, box):
7878
right >= left
7979

8080

81-
def assert_all(obj):
82-
"""
83-
Test helper to call call obj.all() the appropriate number of times on
84-
a Series or DataFrame.
85-
"""
86-
if isinstance(obj, pd.DataFrame):
87-
assert obj.all().all()
88-
else:
89-
assert obj.all()
90-
91-
9281
# ------------------------------------------------------------------
9382
# Comparisons
9483

@@ -578,17 +567,17 @@ def test_comparison_tzawareness_compat(self, op, box_df_fail):
578567
op(dz, np.array(list(dr), dtype=object))
579568

580569
# The aware==aware and naive==naive comparisons should *not* raise
581-
assert_all(dr == dr)
582-
assert_all(dr == list(dr))
583-
assert_all(list(dr) == dr)
584-
assert_all(np.array(list(dr), dtype=object) == dr)
585-
assert_all(dr == np.array(list(dr), dtype=object))
586-
587-
assert_all(dz == dz)
588-
assert_all(dz == list(dz))
589-
assert_all(list(dz) == dz)
590-
assert_all(np.array(list(dz), dtype=object) == dz)
591-
assert_all(dz == np.array(list(dz), dtype=object))
570+
assert np.all(dr == dr)
571+
assert np.all(dr == list(dr))
572+
assert np.all(list(dr) == dr)
573+
assert np.all(np.array(list(dr), dtype=object) == dr)
574+
assert np.all(dr == np.array(list(dr), dtype=object))
575+
576+
assert np.all(dz == dz)
577+
assert np.all(dz == list(dz))
578+
assert np.all(list(dz) == dz)
579+
assert np.all(np.array(list(dz), dtype=object) == dz)
580+
assert np.all(dz == np.array(list(dz), dtype=object))
592581

593582
@pytest.mark.parametrize(
594583
"op",
@@ -606,12 +595,12 @@ def test_comparison_tzawareness_compat_scalars(self, op, box_with_array):
606595
ts = pd.Timestamp("2000-03-14 01:59")
607596
ts_tz = pd.Timestamp("2000-03-14 01:59", tz="Europe/Amsterdam")
608597

609-
assert_all(dr > ts)
598+
assert np.all(dr > ts)
610599
msg = "Cannot compare tz-naive and tz-aware"
611600
with pytest.raises(TypeError, match=msg):
612601
op(dr, ts_tz)
613602

614-
assert_all(dz > ts_tz)
603+
assert np.all(dz > ts_tz)
615604
with pytest.raises(TypeError, match=msg):
616605
op(dz, ts)
617606

pandas/tests/arrays/test_numpy.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,18 @@ def test_basic_binop():
211211
result = x + x
212212
expected = PandasArray(np.array([2, 4, 6]))
213213
tm.assert_extension_array_equal(result, expected)
214+
215+
216+
@pytest.mark.parametrize("dtype", [None, object])
217+
def test_setitem_object_typecode(dtype):
218+
arr = PandasArray(np.array(["a", "b", "c"], dtype=dtype))
219+
arr[0] = "t"
220+
expected = PandasArray(np.array(["t", "b", "c"], dtype=dtype))
221+
tm.assert_extension_array_equal(arr, expected)
222+
223+
224+
def test_setitem_no_coercion():
225+
# https://github.com/pandas-dev/pandas/issues/28150
226+
arr = PandasArray(np.array([1, 2, 3]))
227+
with pytest.raises(ValueError, match="int"):
228+
arr[0] = "a"

pandas/tests/dtypes/test_missing.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,20 @@ def test_array_equivalent_str():
360360
)
361361

362362

363+
def test_array_equivalent_nested():
364+
# reached in groupby aggregations, make sure we use np.any when checking
365+
# if the comparison is truthy
366+
left = np.array([np.array([50, 70, 90]), np.array([20, 30, 40])], dtype=object)
367+
right = np.array([np.array([50, 70, 90]), np.array([20, 30, 40])], dtype=object)
368+
369+
assert array_equivalent(left, right, strict_nan=True)
370+
assert not array_equivalent(left, right[::-1], strict_nan=True)
371+
372+
left = np.array([np.array([50, 50, 50]), np.array([40, 40, 40])], dtype=object)
373+
right = np.array([50, 40])
374+
assert not array_equivalent(left, right, strict_nan=True)
375+
376+
363377
@pytest.mark.parametrize(
364378
"dtype, na_value",
365379
[

pandas/tests/frame/test_indexing.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,23 +2160,6 @@ def test_iat(self, float_frame):
21602160
expected = float_frame.at[row, col]
21612161
assert result == expected
21622162

2163-
def test_nested_exception(self):
2164-
# Ignore the strange way of triggering the problem
2165-
# (which may get fixed), it's just a way to trigger
2166-
# the issue or reraising an outer exception without
2167-
# a named argument
2168-
df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]}).set_index(
2169-
["a", "b"]
2170-
)
2171-
index = list(df.index)
2172-
index[0] = ["a", "b"]
2173-
df.index = index
2174-
2175-
try:
2176-
repr(df)
2177-
except Exception as e:
2178-
assert type(e) != UnboundLocalError
2179-
21802163
@pytest.mark.parametrize(
21812164
"method,expected_values",
21822165
[

pandas/tests/indexes/interval/test_astype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def test_subtype_integer(self, subtype):
143143
tm.assert_index_equal(result, expected)
144144

145145
# raises with NA
146-
msg = "Cannot convert NA to integer"
146+
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
147147
with pytest.raises(ValueError, match=msg):
148148
index.insert(0, np.nan).astype(dtype)
149149

pandas/tests/indexes/test_numeric.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,17 @@ def test_astype(self):
242242
# GH 13149
243243
for dtype in ["int16", "int32", "int64"]:
244244
i = Float64Index([0, 1.1, np.NAN])
245-
msg = "Cannot convert NA to integer"
245+
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
246246
with pytest.raises(ValueError, match=msg):
247247
i.astype(dtype)
248248

249+
def test_cannot_cast_inf_to_int(self):
250+
idx = pd.Float64Index([1, 2, np.inf])
251+
252+
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
253+
with pytest.raises(ValueError, match=msg):
254+
idx.astype(int)
255+
249256
def test_type_coercion_fail(self, any_int_dtype):
250257
# see gh-15832
251258
msg = "Trying to coerce float values to integers"

pandas/tests/indexing/common.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -210,22 +210,23 @@ def _print(result, error=None):
210210
try:
211211
rs = getattr(obj, method1).__getitem__(_axify(obj, k1, a))
212212

213-
try:
214-
xp = self.get_result(obj, method2, k2, a)
215-
except Exception:
216-
result = "no comp"
217-
_print(result)
218-
return
213+
with catch_warnings(record=True):
214+
filterwarnings("ignore", "\\n.ix", FutureWarning)
215+
try:
216+
xp = self.get_result(obj, method2, k2, a)
217+
except (KeyError, IndexError):
218+
# TODO: why is this allowed?
219+
result = "no comp"
220+
_print(result)
221+
return
219222

220223
detail = None
221224

222225
try:
223226
if is_scalar(rs) and is_scalar(xp):
224227
assert rs == xp
225-
elif xp.ndim == 1:
226-
tm.assert_series_equal(rs, xp)
227-
elif xp.ndim == 2:
228-
tm.assert_frame_equal(rs, xp)
228+
else:
229+
tm.assert_equal(rs, xp)
229230
result = "ok"
230231
except AssertionError as e:
231232
detail = str(e)
@@ -242,7 +243,7 @@ def _print(result, error=None):
242243

243244
except AssertionError:
244245
raise
245-
except Exception as detail:
246+
except (IndexError, TypeError, KeyError) as detail:
246247

247248
# if we are in fails, the ok, otherwise raise it
248249
if fails is not None:

pandas/tests/io/json/conftest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import pytest
2+
3+
4+
@pytest.fixture(params=["split", "records", "index", "columns", "values"])
5+
def orient(request):
6+
"""
7+
Fixture for orients excluding the table format.
8+
"""
9+
return request.param

0 commit comments

Comments
 (0)