Skip to content

Commit e6737f6

Browse files
committed
Merge branch 'master' into numexpr-bugfix
2 parents 9b7c504 + 7f61524 commit e6737f6

26 files changed

+238
-256
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,5 @@ You can also triage issues which may include reproducing bug reports, or asking
233233
Or maybe through using pandas you have an idea of your own or are looking for something in the documentation and thinking ‘this can be improved’...you can do something about it!
234234

235235
Feel free to ask questions on the [mailing list](https://groups.google.com/forum/?fromgroups#!forum/pydata) or on [Gitter](https://gitter.im/pydata/pandas).
236+
237+
As contributors and maintainers to this project, you are expected to abide by pandas' code of conduct. More information can be found at: [Contributor Code of Conduct](https://github.com/pandas-dev/pandas/blob/master/.github/CODE_OF_CONDUCT.md)

doc/source/whatsnew/v0.25.1.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Indexing
8484

8585
- Bug in partial-string indexing returning a NumPy array rather than a ``Series`` when indexing with a scalar like ``.loc['2015']`` (:issue:`27516`)
8686
- Break reference cycle involving :class:`Index` to allow garbage collection of :class:`Index` objects without running the GC. (:issue:`27585`)
87-
-
87+
- Fix regression in assigning values to a single column of a DataFrame with a ``MultiIndex`` columns (:issue:`27841`).
8888
-
8989

9090
Missing
@@ -133,7 +133,7 @@ Reshaping
133133

134134
Sparse
135135
^^^^^^
136-
136+
- Bug in reductions for :class:`Series` with Sparse dtypes (:issue:`27080`)
137137
-
138138
-
139139
-

doc/source/whatsnew/v1.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ Plotting
165165

166166
- Bug in :meth:`Series.plot` not able to plot boolean values (:issue:`23719`)
167167
-
168+
- Bug in :meth:`DataFrame.plot` when ``kind='box'`` and data contains datetime or timedelta data. These types are now automatically dropped (:issue:`22799`)
168169

169170
Groupby/resample/rolling
170171
^^^^^^^^^^^^^^^^^^^^^^^^

pandas/core/arrays/categorical.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import operator
12
from shutil import get_terminal_size
23
import textwrap
34
from typing import Type, Union, cast
@@ -77,7 +78,9 @@
7778
)
7879

7980

80-
def _cat_compare_op(opname):
81+
def _cat_compare_op(op):
82+
opname = "__{op}__".format(op=op.__name__)
83+
8184
def f(self, other):
8285
# On python2, you can usually compare any type to any type, and
8386
# Categoricals can be seen as a custom type, but having different
@@ -88,6 +91,9 @@ def f(self, other):
8891
return NotImplemented
8992

9093
other = lib.item_from_zerodim(other)
94+
if is_list_like(other) and len(other) != len(self):
95+
# TODO: Could this fail if the categories are listlike objects?
96+
raise ValueError("Lengths must match.")
9197

9298
if not self.ordered:
9399
if opname in ["__lt__", "__gt__", "__le__", "__ge__"]:
@@ -1240,12 +1246,12 @@ def map(self, mapper):
12401246
new_categories = new_categories.insert(len(new_categories), np.nan)
12411247
return np.take(new_categories, self._codes)
12421248

1243-
__eq__ = _cat_compare_op("__eq__")
1244-
__ne__ = _cat_compare_op("__ne__")
1245-
__lt__ = _cat_compare_op("__lt__")
1246-
__gt__ = _cat_compare_op("__gt__")
1247-
__le__ = _cat_compare_op("__le__")
1248-
__ge__ = _cat_compare_op("__ge__")
1249+
__eq__ = _cat_compare_op(operator.eq)
1250+
__ne__ = _cat_compare_op(operator.ne)
1251+
__lt__ = _cat_compare_op(operator.lt)
1252+
__gt__ = _cat_compare_op(operator.gt)
1253+
__le__ = _cat_compare_op(operator.le)
1254+
__ge__ = _cat_compare_op(operator.ge)
12491255

12501256
# for Series/ndarray like compat
12511257
@property

pandas/core/arrays/datetimelike.py

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
is_datetime64tz_dtype,
2323
is_datetime_or_timedelta_dtype,
2424
is_dtype_equal,
25-
is_extension_array_dtype,
2625
is_float_dtype,
2726
is_integer_dtype,
2827
is_list_like,
@@ -1230,29 +1229,17 @@ def __add__(self, other):
12301229
if not is_period_dtype(self):
12311230
maybe_integer_op_deprecated(self)
12321231
result = self._addsub_int_array(other, operator.add)
1233-
elif is_float_dtype(other):
1234-
# Explicitly catch invalid dtypes
1235-
raise TypeError(
1236-
"cannot add {dtype}-dtype to {cls}".format(
1237-
dtype=other.dtype, cls=type(self).__name__
1238-
)
1239-
)
1240-
elif is_period_dtype(other):
1241-
# if self is a TimedeltaArray and other is a PeriodArray with
1242-
# a timedelta-like (i.e. Tick) freq, this operation is valid.
1243-
# Defer to the PeriodArray implementation.
1244-
# In remaining cases, this will end up raising TypeError.
1245-
return NotImplemented
1246-
elif is_extension_array_dtype(other):
1247-
# Categorical op will raise; defer explicitly
1248-
return NotImplemented
1249-
else: # pragma: no cover
1232+
else:
1233+
# Includes Categorical, other ExtensionArrays
1234+
# For PeriodDtype, if self is a TimedeltaArray and other is a
1235+
# PeriodArray with a timedelta-like (i.e. Tick) freq, this
1236+
# operation is valid. Defer to the PeriodArray implementation.
1237+
# In remaining cases, this will end up raising TypeError.
12501238
return NotImplemented
12511239

12521240
if is_timedelta64_dtype(result) and isinstance(result, np.ndarray):
12531241
from pandas.core.arrays import TimedeltaArray
12541242

1255-
# TODO: infer freq?
12561243
return TimedeltaArray(result)
12571244
return result
12581245

@@ -1302,29 +1289,13 @@ def __sub__(self, other):
13021289
if not is_period_dtype(self):
13031290
maybe_integer_op_deprecated(self)
13041291
result = self._addsub_int_array(other, operator.sub)
1305-
elif isinstance(other, ABCIndexClass):
1306-
raise TypeError(
1307-
"cannot subtract {cls} and {typ}".format(
1308-
cls=type(self).__name__, typ=type(other).__name__
1309-
)
1310-
)
1311-
elif is_float_dtype(other):
1312-
# Explicitly catch invalid dtypes
1313-
raise TypeError(
1314-
"cannot subtract {dtype}-dtype from {cls}".format(
1315-
dtype=other.dtype, cls=type(self).__name__
1316-
)
1317-
)
1318-
elif is_extension_array_dtype(other):
1319-
# Categorical op will raise; defer explicitly
1320-
return NotImplemented
1321-
else: # pragma: no cover
1292+
else:
1293+
# Includes ExtensionArrays, float_dtype
13221294
return NotImplemented
13231295

13241296
if is_timedelta64_dtype(result) and isinstance(result, np.ndarray):
13251297
from pandas.core.arrays import TimedeltaArray
13261298

1327-
# TODO: infer freq?
13281299
return TimedeltaArray(result)
13291300
return result
13301301

pandas/core/arrays/datetimes.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@ def wrapper(self, other):
223223
result = op(self.view("i8"), other.view("i8"))
224224
o_mask = other._isnan
225225

226-
result = com.values_from_object(result)
227-
228226
if o_mask.any():
229227
result[o_mask] = nat_result
230228

pandas/core/arrays/integer.py

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
is_scalar,
2222
)
2323
from pandas.core.dtypes.dtypes import register_extension_dtype
24-
from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries
24+
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
2525
from pandas.core.dtypes.missing import isna, notna
2626

2727
from pandas.core import nanops, ops
@@ -592,25 +592,29 @@ def _values_for_argsort(self) -> np.ndarray:
592592

593593
@classmethod
594594
def _create_comparison_method(cls, op):
595-
def cmp_method(self, other):
595+
op_name = op.__name__
596596

597-
op_name = op.__name__
598-
mask = None
597+
def cmp_method(self, other):
599598

600-
if isinstance(other, (ABCSeries, ABCIndexClass)):
599+
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
601600
# Rely on pandas to unbox and dispatch to us.
602601
return NotImplemented
603602

603+
other = lib.item_from_zerodim(other)
604+
mask = None
605+
604606
if isinstance(other, IntegerArray):
605607
other, mask = other._data, other._mask
606608

607609
elif is_list_like(other):
608610
other = np.asarray(other)
609-
if other.ndim > 0 and len(self) != len(other):
611+
if other.ndim > 1:
612+
raise NotImplementedError(
613+
"can only perform ops with 1-d structures"
614+
)
615+
if len(self) != len(other):
610616
raise ValueError("Lengths must match to compare")
611617

612-
other = lib.item_from_zerodim(other)
613-
614618
# numpy will show a DeprecationWarning on invalid elementwise
615619
# comparisons, this will raise in the future
616620
with warnings.catch_warnings():
@@ -683,31 +687,31 @@ def _maybe_mask_result(self, result, mask, other, op_name):
683687

684688
@classmethod
685689
def _create_arithmetic_method(cls, op):
686-
def integer_arithmetic_method(self, other):
690+
op_name = op.__name__
687691

688-
op_name = op.__name__
689-
mask = None
692+
def integer_arithmetic_method(self, other):
690693

691-
if isinstance(other, (ABCSeries, ABCIndexClass)):
694+
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
692695
# Rely on pandas to unbox and dispatch to us.
693696
return NotImplemented
694697

695-
if getattr(other, "ndim", 0) > 1:
696-
raise NotImplementedError("can only perform ops with 1-d structures")
698+
other = lib.item_from_zerodim(other)
699+
mask = None
697700

698701
if isinstance(other, IntegerArray):
699702
other, mask = other._data, other._mask
700703

701-
elif getattr(other, "ndim", None) == 0:
702-
other = other.item()
703-
704704
elif is_list_like(other):
705705
other = np.asarray(other)
706-
if not other.ndim:
707-
other = other.item()
708-
elif other.ndim == 1:
709-
if not (is_float_dtype(other) or is_integer_dtype(other)):
710-
raise TypeError("can only perform ops with numeric values")
706+
if other.ndim > 1:
707+
raise NotImplementedError(
708+
"can only perform ops with 1-d structures"
709+
)
710+
if len(self) != len(other):
711+
raise ValueError("Lengths must match")
712+
if not (is_float_dtype(other) or is_integer_dtype(other)):
713+
raise TypeError("can only perform ops with numeric values")
714+
711715
else:
712716
if not (is_float(other) or is_integer(other)):
713717
raise TypeError("can only perform ops with numeric values")

pandas/core/arrays/sparse.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,9 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
16931693
for sp_value, fv in zip(sp_values, fill_value)
16941694
)
16951695
return arrays
1696+
elif is_scalar(sp_values):
1697+
# e.g. reductions
1698+
return sp_values
16961699

16971700
return self._simple_new(
16981701
sp_values, self.sp_index, SparseDtype(sp_values.dtype, fill_value)

pandas/core/frame.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ def style(self):
770770
_shared_docs[
771771
"items"
772772
] = r"""
773-
Iterator over (column name, Series) pairs.
773+
Iterate over (column name, Series) pairs.
774774
775775
Iterates over the DataFrame columns, returning a tuple with
776776
the column name and the content as a Series.
@@ -845,8 +845,8 @@ def iterrows(self):
845845
846846
See Also
847847
--------
848-
itertuples : Iterate over DataFrame rows as namedtuples of the values.
849-
items : Iterate over (column name, Series) pairs.
848+
DataFrame.itertuples : Iterate over DataFrame rows as namedtuples of the values.
849+
DataFrame.items : Iterate over (column name, Series) pairs.
850850
851851
Notes
852852
-----
@@ -3447,15 +3447,14 @@ def _get_info_slice(obj, indexer):
34473447
if not is_list_like(exclude):
34483448
exclude = (exclude,) if exclude is not None else ()
34493449

3450-
selection = tuple(map(frozenset, (include, exclude)))
3450+
selection = (frozenset(include), frozenset(exclude))
34513451

34523452
if not any(selection):
34533453
raise ValueError("at least one of include or exclude must be nonempty")
34543454

34553455
# convert the myriad valid dtypes object to a single representation
3456-
include, exclude = map(
3457-
lambda x: frozenset(map(infer_dtype_from_object, x)), selection
3458-
)
3456+
include = frozenset(infer_dtype_from_object(x) for x in include)
3457+
exclude = frozenset(infer_dtype_from_object(x) for x in exclude)
34593458
for dtypes in (include, exclude):
34603459
invalidate_string_dtypes(dtypes)
34613460

pandas/core/generic.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,12 @@ def _repr_data_resource_(self):
21792179
... df1.to_excel(writer, sheet_name='Sheet_name_1')
21802180
... df2.to_excel(writer, sheet_name='Sheet_name_2')
21812181
2182+
ExcelWriter can also be used to append to an existing Excel file:
2183+
2184+
>>> with pd.ExcelWriter('output.xlsx',
2185+
... mode='a') as writer: # doctest: +SKIP
2186+
... df.to_excel(writer, sheet_name='Sheet_name_3')
2187+
21822188
To set the library that is used to write the Excel file,
21832189
you can pass the `engine` keyword (the default engine is
21842190
automatically chosen depending on the file extension):

0 commit comments

Comments
 (0)