8000 Merge branch 'master' of https://github.com/pandas-dev/pandas into opcom · pandas-dev/pandas@7f337d2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7f337d2

Browse files
committed
Merge branch 'master' of https://github.com/pandas-dev/pandas into opcom
2 parents d19282d + 6afa2ad commit 7f337d2

File tree

8 files changed

+56
-7
lines changed

8 files changed

+56
-7
lines changed

doc/source/whatsnew/v0.25.1.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ Groupby/resample/rolling
120120

121121
- Bug in :meth:`pandas.core.groupby.DataFrameGroupBy.transform` where applying a timezone conversion lambda function would drop timezone information (:issue:`27496`)
122122
- Bug in windowing over read-only arrays (:issue:`27766`)
123-
-
123+
- Fixed segfault in `pandas.core.groupby.DataFrameGroupBy.quantile` when an invalid quantile was passed (:issue:`27470`)
124124
-
125125

126126
Reshaping

doc/source/whatsnew/v1.0.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ I/O
163163
Plotting
164164
^^^^^^^^
165165

166-
-
166+
- Bug in :meth:`Series.plot` not able to plot boolean values (:issue:`23719`)
167167
-
168168

169169
Groupby/resample/rolling

pandas/_libs/groupby.pyx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,11 @@ def group_quantile(ndarray[float64_t] out,
719719
ndarray[int64_t] counts, non_na_counts, sort_arr
720720

721721
assert values.shape[0] == N
722+
723+
if not (0 <= q <= 1):
724+
raise ValueError("'q' must be between 0 and 1. Got"
725+
" '{}' instead".format(q))
726+
722727
inter_methods = {
723728
'linear': INTERPOLATION_LINEAR,
724729
'lower': INTERPOLATION_LOWER,

pandas/core/internals/blocks.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,8 +738,11 @@ def replace(
738738
# If we cannot replace with own dtype, convert to ObjectBlock and
739739
# retry
740740
if not self._can_hold_element(to_replace):
741-
# TODO: we should be able to infer at this point that there is
742-
# nothing to replace
741+
if not isinstance(to_replace, list):
742+
if inplace:
743+
return [self]
744+
return [self.copy()]
745+
743746
# GH 22083, TypeError or ValueError occurred within error handling
744747
# causes infinite loop. Cast and retry only if not objectblock.
745748
if is_object_dtype(self):
@@ -764,14 +767,27 @@ def replace(
764767
filtered_out = ~self.mgr_locs.isin(filter)
765768
mask[filtered_out.nonzero()[0]] = False
766769

770+
if not mask.any():
771+
if inplace:
772+
return [self]
773+
return [self.copy()]
774+
767775
try:
768776
blocks = self.putmask(mask, value, inplace=inplace)
777+
# Note: it is _not_ the case that self._can_hold_element(value)
778+
# is always true at this point. In particular, that can fail
779+
# for:
780+
# "2u" with bool-dtype, float-dtype
781+
# 0.5 with int64-dtype
782+
# np.nan with int64-dtype
769783
except (TypeError, ValueError):
770784
# GH 22083, TypeError or ValueError occurred within error handling
771785
# causes infinite loop. Cast and retry only if not objectblock.
772786
if is_object_dtype(self):
773787
raise
774788

789+
assert not self._can_hold_element(value), value
790+
775791
# try again with a compatible block
776792
block = self.astype(object)
777793
return block.replace(
@@ -924,6 +940,7 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0, transpose=False)
924940

925941
# if we are passed a scalar None, convert it here
926942
if not is_list_like(new) and isna(new) and not self.is_object:
943+
# FIXME: make sure we have compatible NA
927944
new = self.fill_value
928945

929946
if self._can_hold_element(new):

pandas/plotting/_core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,8 @@ class PlotAccessor(PandasObject):
586586
mark_right : bool, default True
587587
When using a secondary_y axis, automatically mark the column
588588
labels with "(right)" in the legend
589+
include_bool : bool, default is False
590+
If True, boolean values can be plotted
589591
`**kwds` : keywords
590592
Options to pass to matplotlib plotting method
591593

pandas/plotting/_matplotlib/core.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def __init__(
106106
colormap=None,
107107
table=False,
108108
layout=None,
109+
include_bool=False,
109110
**kwds
110111
):
111112

@@ -191,6 +192,7 @@ def __init__(
191192
self.colormap = colormap
192193

193194
self.table = table
195+
self.include_bool = include_bool
194196

195197
self.kwds = kwds
196198

@@ -400,9 +402,12 @@ def _compute_plot_data(self):
400402
# GH16953, _convert is needed as fallback, for ``Series``
401403
# with ``dtype == object``
402404
data = data._convert(datetime=True, timedelta=True)
403-
numeric_data = data.select_dtypes(
404-
include=[np.number, "datetime", "datetimetz", "timedelta"]
405-
)
405+
select_include_type = [np.number, "datetime", "datetimetz", "timedelta"]
406+
407+
# GH23719, allow plotting boolean
408+
if self.include_bool is True:
409+
select_include_type.append(np.bool_)
410+
numeric_data = data.select_dtypes(include=select_include_type)
406411

407412
try:
408413
is_empty = numeric_data.empty

pandas/tests/groupby/test_function.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,17 @@ def test_quantile_raises():
12471247
df.groupby("key").quantile()
12481248

12491249

1250+
def test_quantile_out_of_bounds_q_raises():
1251+
# https://github.com/pandas-dev/pandas/issues/27470
1252+
df = pd.DataFrame(dict(a=[0, 0, 0, 1, 1, 1], b=range(6)))
1253+
g = df.groupby([0, 0, 0, 1, 1, 1])
1254+
with pytest.raises(ValueError, match="Got '50.0' instead"):
1255+
g.quantile(50)
1256+
1257+
with pytest.raises(ValueError, match="Got '-1.0' instead"):
1258+
g.quantile(-1)
1259+
1260+
12501261
# pipe
12511262
# --------------------------------
12521263

pandas/tests/plotting/test_series.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,15 @@ def test_label(self):
167167
ax.legend() # draw it
168168
self._check_legend_labels(ax, labels=["LABEL"])
169169

170+
def test_boolean(self):
171+
# GH 23719
172+
s = Series([False, False, True])
173+
_check_plot_works(s.plot, include_bool=True)
174+
175+
msg = "no numeric data to plot"
176+
with pytest.raises(TypeError, match=msg):
177+
_check_plot_works(s.plot)
178+
170179
def test_line_area_nan_series(self):
171180
values = [1, 2, np.nan, 3]
172181
s = Series(values)

0 commit comments

Comments
 (0)
0