Skip to content

Commit

Permalink
BUG: Groupby quantiles incorrect bins #33200 (#33644)
Browse files Browse the repository at this point in the history
  • Loading branch information
mabelvj authored May 25, 2020
1 parent d75100d commit 2740fb4
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ Groupby/resample/rolling
- Bug in :meth:`DataFrame.resample` where an ``AmbiguousTimeError`` would be raised when the resulting timezone aware :class:`DatetimeIndex` had a DST transition at midnight (:issue:`25758`)
- Bug in :meth:`DataFrame.groupby` where a ``ValueError`` would be raised when grouping by a categorical column with read-only categories and ``sort=False`` (:issue:`33410`)
- Bug in :meth:`GroupBy.first` and :meth:`GroupBy.last` where None is not preserved in object dtype (:issue:`32800`)
- Bug in :meth:`GroupBy.quantile` causes the quantiles to be shifted when the ``by`` axis contains ``NaN`` (:issue:`33200`, :issue:`33569`)
- Bug in :meth:`Rolling.min` and :meth:`Rolling.max`: Growing memory usage after multiple calls when using a fixed window (:issue:`30726`)
- Bug in :meth:`Series.groupby` would raise ``ValueError`` when grouping by :class:`PeriodIndex` level (:issue:`34010`)
- Bug in :meth:`GroupBy.agg`, :meth:`GroupBy.transform`, and :meth:`GroupBy.resample` where subclasses are not preserved (:issue:`28330`)
Expand Down
8 changes: 7 additions & 1 deletion pandas/_libs/groupby.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,13 @@ def group_quantile(ndarray[float64_t] out,
non_na_counts[lab] += 1

# Get an index of values sorted by labels and then values
order = (values, labels)
if labels.any():
# Put '-1' (NaN) labels as the last group so it does not interfere
# with the calculations.
labels_for_lexsort = np.where(labels == -1, labels.max() + 1, labels)
else:
labels_for_lexsort = labels
order = (values, labels_for_lexsort)
sort_arr = np.lexsort(order).astype(np.int64, copy=False)

with nogil:
Expand Down
29 changes: 23 additions & 6 deletions pandas/tests/groupby/test_quantile.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,32 @@ def test_quantile_missing_group_values_no_segfaults():
grp.quantile()


def test_quantile_missing_group_values_correct_results():
# GH 28662
data = np.array([1.0, np.nan, 3.0, np.nan])
df = pd.DataFrame(dict(key=data, val=range(4)))
@pytest.mark.parametrize(
"key, val, expected_key, expected_val",
[
([1.0, np.nan, 3.0, np.nan], range(4), [1.0, 3.0], [0.0, 2.0]),
([1.0, np.nan, 2.0, 2.0], range(4), [1.0, 2.0], [0.0, 2.5]),
(["a", "b", "b", np.nan], range(4), ["a", "b"], [0, 1.5]),
([0], [42], [0], [42.0]),
([], [], np.array([], dtype="float64"), np.array([], dtype="float64")),
],
)
def test_quantile_missing_group_values_correct_results(
key, val, expected_key, expected_val
):
# GH 28662, GH 33200, GH 33569
df = pd.DataFrame({"key": key, "val": val})

result = df.groupby("key").quantile()
expected = pd.DataFrame(
[1.0, 3.0], index=pd.Index([1.0, 3.0], name="key"), columns=["val"]
expected_val, index=pd.Index(expected_key, name="key"), columns=["val"]
)

grp = df.groupby("key")

result = grp.quantile(0.5)
tm.assert_frame_equal(result, expected)

result = grp.quantile()
tm.assert_frame_equal(result, expected)


Expand Down

0 comments on commit 2740fb4

Please sign in to comment.