Repository: scikit-learn/scikit-learn
File: sklearn/utils/tests/test_stats.py (Python)

Code before:
    if average:
        method = "averaged_inverted_cdf"
    else:
        method = "inverted_cdf"

    assert score == np.percentile(y, percentile_rank, method=method)


@pytest.mark.parametrize("percentile_rank", [50, 100])
def test_weighted_percentile_plus_one_clip_max(percentile_rank):
    """Check `j+1` index is clipped to max, when `average=True`.

    `percentile_plus_one_indices` can exceed max index when `percentile_indices`
    is already at max index.
    Note that when `g` (Hyndman and Fan) / `fraction_above` is greater than 0,
    `j+1` (Hyndman and Fan) / `percentile_plus_one_indices` is calculated but
    never used, so it does not matter what this value is.
    When percentile of percentile rank 100 falls exactly on the last value in the
    `weighted_cdf`, `g=0` and `percentile_indices` is at max index. In this case
    we set `percentile_plus_one_indices` to be max index as well, so the result is
    the average of 2x the max index (i.e. last value of `weighted_cdf`).
    """
    # Note for both `percentile_rank`s 50 and 100,`percentile_indices` is already at
    # max index
    y = np.array([[0, 0], [1, 1]])
    sw = np.array([[0.1, 0.1], [2, 2]])
    score = _weighted_percentile(y, sw, percentile_rank)
    for idx in range(2):
        assert score[idx] == approx(1.0)


def test_weighted_percentile_equal():
    """Check `weighted_percentile` with unit weights and all 0 values in `array`."""
    y = np.zeros(102, dtype=np.float64)
    sw = np.ones(102, dtype=np.float64)
    score = _weighted_percentile(y, sw, 50)
    assert approx(score) == 0


def test_weighted_percentile_all_zero_weights():
    """Check `weighted_percentile` with all weights equal to 0 returns last index."""
    y = np.arange(10)
    sw = np.zeros(10)
    value = _weighted_percentile(y, sw, 50)
    assert approx(value) == 9.0


@pytest.mark.parametrize("average", [True, False])
@pytest.mark.parametrize("percentile_rank, expected_value", [(0, 2), (50, 3), (100, 5)])
def test_weighted_percentile_ignores_zero_weight(
    average, percentile_rank, expected_value

Review comment (suggestion):
Use unit weights in the first column to make the test less redundant:

```suggestion
    sw = np.array([[1, 0.1], [1, 2]])
```

Code after:

    assert approx(score) == np.percentile(y, percentile_rank, method=method)


@pytest.mark.parametrize("percentile_rank", [50, 100])
def test_weighted_percentile_plus_one_clip_max(percentile_rank):
    """Check `j+1` index is clipped to max, when `average=True`.

    `percentile_plus_one_indices` can exceed max index when `percentile_indices`
    is already at max index.
    Note that when `g` (Hyndman and Fan) / `fraction_above` is greater than 0,
    `j+1` (Hyndman and Fan) / `percentile_plus_one_indices` is calculated but
    never used, so it does not matter what this value is.
    When percentile of percentile rank 100 falls exactly on the last value in the
    `weighted_cdf`, `g=0` and `percentile_indices` is at max index. In this case
    we set `percentile_plus_one_indices` to be max index as well, so the result is
    the average of 2x the max index (i.e. last value of `weighted_cdf`).
    """
    # Note for both `percentile_rank`s 50 and 100,`percentile_indices` is already at
    # max index
    y = np.array([[0, 0], [1, 1]])
    sw = np.array([[0.1, 0.2], [2, 3]])
    score = _weighted_percentile(y, sw, percentile_rank, average=True)
    for idx in range(2):
        assert score[idx] == approx(1.0)


def test_weighted_percentile_equal():
    """Check `weighted_percentile` with unit weights and all 0 values in `array`."""
    y = np.zeros(102, dtype=np.float64)
    sw = np.ones(102, dtype=np.float64)
    score = _weighted_percentile(y, sw, 50)
    assert approx(score) == 0


# XXX: is this really what we want? Shouldn't we raise instead?
# https://github.com/scikit-learn/scikit-learn/issues/31032
def test_weighted_percentile_all_zero_weights():
    """Check `weighted_percentile` with all weights equal to 0 returns last index."""
    y = np.arange(10)
    sw = np.zeros(10)
    value = _weighted_percentile(y, sw, 50)
    assert approx(value) == 9.0


@pytest.mark.parametrize("average", [True, False])
@pytest.mark.parametrize("percentile_rank, expected_value", [(0, 2), (50, 3), (100, 5)])
def test_weighted_percentile_ignores_zero_weight(
    average, percentile_rank, expected_value
):
    """Check leading, trailing and middle 0 weights behave correctly.