Skip to content

Commit 6c41c4f

Browse files
Implement dpnp.digitize() (#1847)
* Implement dpnp.digitize * Update cupy tests for digitize func * Update skipped_tests files * Add tests in test_sycl_queue and test_usm_type * Return pylint disable * Handle empty bins * Small update cupy tests * Add dpnp tests for dpnp.digitize * Increase code coverage * Apply remarks * Move tests from test_statistic to test_histogram * Add test with different dtypes
1 parent 9021941 commit 6c41c4f

File tree

7 files changed

+196
-119
lines changed

7 files changed

+196
-119
lines changed

dpnp/dpnp_iface_histograms.py

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import dpnp
4747

4848
__all__ = [
49+
"digitize",
4950
"histogram",
5051
"histogram_bin_edges",
5152
]
@@ -208,6 +209,98 @@ def _search_sorted_inclusive(a, v):
208209
)
209210

210211

212+
def digitize(x, bins, right=False):
213+
"""
214+
Return the indices of the bins to which each value in input array belongs.
215+
216+
For full documentation refer to :obj:`numpy.digitize`.
217+
218+
Parameters
219+
----------
220+
a : {dpnp.ndarray, usm_ndarray}
221+
Input array to be binned.
222+
bins : {dpnp.ndarray, usm_ndarray}
223+
Array of bins. It has to be 1-dimensional and monotonic
224+
increasing or decreasing.
225+
right : bool, optional
226+
Indicates whether the intervals include the right or the left bin edge.
227+
Default: ``False``.
228+
229+
Returns
230+
-------
231+
indices : dpnp.ndarray
232+
Array of indices with the same shape as `x`.
233+
234+
Notes
235+
-----
236+
This will not raise an exception when the input array is
237+
not monotonic.
238+
239+
See Also
240+
--------
241+
:obj:`dpnp.bincount` : Count number of occurrences of each value in array
242+
of non-negative integers.
243+
:obj:`dpnp.histogram` : Compute the histogram of a data set.
244+
:obj:`dpnp.unique` : Find the unique elements of an array.
245+
:obj:`dpnp.searchsorted` : Find indices where elements should be inserted
246+
to maintain order.
247+
248+
Examples
249+
--------
250+
>>> import dpnp as np
251+
>>> x = np.array([0.2, 6.4, 3.0, 1.6])
252+
>>> bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0])
253+
>>> inds = np.digitize(x, bins)
254+
>>> inds
255+
array([1, 4, 3, 2])
256+
>>> for n in range(x.size):
257+
... print(bins[inds[n]-1], "<=", x[n], "<", bins[inds[n]])
258+
...
259+
0. <= 0.2 < 1.
260+
4. <= 6.4 < 10.
261+
2.5 <= 3. < 4.
262+
1. <= 1.6 < 2.5
263+
264+
>>> x = np.array([1.2, 10.0, 12.4, 15.5, 20.])
265+
>>> bins = np.array([0, 5, 10, 15, 20])
266+
>>> np.digitize(x, bins, right=True)
267+
array([1, 2, 3, 4, 4])
268+
>>> np.digitize(x, bins, right=False)
269+
array([1, 3, 3, 4, 5])
270+
271+
"""
272+
273+
dpnp.check_supported_arrays_type(x, bins)
274+
275+
if dpnp.issubdtype(x.dtype, dpnp.complexfloating):
276+
raise TypeError("x may not be complex")
277+
278+
if bins.ndim > 1:
279+
raise ValueError("object too deep for desired array")
280+
if bins.ndim < 1:
281+
raise ValueError("object of too small depth for desired array")
282+
283+
# This is backwards because the arguments below are swapped
284+
side = "left" if right else "right"
285+
286+
# Check if bins are monotonically increasing.
287+
# If bins is empty, the array is considered to be increasing.
288+
# If all bins are NaN, the array is considered to be decreasing.
289+
if bins.size == 0:
290+
bins_increasing = True
291+
else:
292+
bins_increasing = bins[0] <= bins[-1] or (
293+
not dpnp.isnan(bins[0]) and dpnp.isnan(bins[-1])
294+
)
295+
296+
if bins_increasing:
297+
# Use dpnp.searchsorted directly if bins are increasing
298+
return dpnp.searchsorted(bins, x, side=side)
299+
300+
# Reverse bins and adjust indices if bins are decreasing
301+
return bins.size - dpnp.searchsorted(bins[::-1], x, side=side)
302+
303+
211304
def histogram(a, bins=10, range=None, density=None, weights=None):
212305
"""
213306
Compute the histogram of a data set.
@@ -335,8 +428,8 @@ def histogram(a, bins=10, range=None, density=None, weights=None):
335428
n = dpnp.diff(cum_n)
336429

337430
if density:
338-
db = dpnp.diff(bin_edges).astype(dpnp.default_float_type())
339431
# pylint: disable=possibly-used-before-assignment
432+
db = dpnp.diff(bin_edges).astype(dpnp.default_float_type())
340433
return n / db / n.sum(), bin_edges
341434

342435
return n, bin_edges

tests/skipped_tests.tbl

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -613,61 +613,6 @@ tests/third_party/cupy/statistics_tests/test_correlation.py::TestCorrcoef::test_
613613
tests/third_party/cupy/statistics_tests/test_correlation.py::TestCorrcoef::test_corrcoef_rowvar
614614
tests/third_party/cupy/statistics_tests/test_correlation.py::TestCorrcoef::test_corrcoef_y
615615

616-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeInvalid::test_digitize_complex
617-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeInvalid::test_digitize_nd_bins
618-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_digitize_all_nan_bins
619-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_digitize_nan
620-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_digitize_nan_bins
621-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_digitize_nan_bins_decreasing
622-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_digitize_nan_bins_decreasing_repeated
623-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_digitize_nan_bins_repeated
624-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_searchsorted_inf
625-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_0_{right=True}::test_searchsorted_minf
626-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_digitize_all_nan_bins
627-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_digitize_nan
628-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_digitize_nan_bins
629-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_digitize_nan_bins_decreasing
630-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_digitize_nan_bins_decreasing_repeated
631-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_digitize_nan_bins_repeated
632-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_searchsorted_inf
633-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitizeNanInf_param_1_{right=False}::test_searchsorted_minf
634-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_0_{bins=[1.5, 2.5, 4.0, 6.0], increasing=True, right=True, shape=()}::test_digitize
635-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_10_{bins=[1.5, 2.5, 4.0, 6.0], increasing=False, right=False, shape=(10,)}::test_digitize
636-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_11_{bins=[1.5, 2.5, 4.0, 6.0], increasing=False, right=False, shape=(6, 3, 3)}::test_digitize
637-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_12_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=True, right=True, shape=()}::test_digitize
638-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_13_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=True, right=True, shape=(10,)}::test_digitize
639-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_14_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=True, right=True, shape=(6, 3, 3)}::test_digitize
640-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_15_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=True, right=False, shape=()}::test_digitize
641-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_16_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=True, right=False, shape=(10,)}::test_digitize
642-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_17_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=True, right=False, shape=(6, 3, 3)}::test_digitize
643-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_18_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=False, right=True, shape=()}::test_digitize
644-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_19_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=False, right=True, shape=(10,)}::test_digitize
645-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_1_{bins=[1.5, 2.5, 4.0, 6.0], increasing=True, right=True, shape=(10,)}::test_digitize
646-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_20_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=False, right=True, shape=(6, 3, 3)}::test_digitize
647-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_21_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=False, right=False, shape=()}::test_digitize
648-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_22_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=False, right=False, shape=(10,)}::test_digitize
649-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_23_{bins=[-1.0, 1.0, 2.5, 4.0, 20.0], increasing=False, right=False, shape=(6, 3, 3)}::test_digitize
650-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_24_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=True, right=True, shape=()}::test_digitize
651-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_25_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=True, right=True, shape=(10,)}::test_digitize
652-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_26_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=True, right=True, shape=(6, 3, 3)}::test_digitize
653-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_27_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=True, right=False, shape=()}::test_digitize
654-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_28_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=True, right=False, shape=(10,)}::test_digitize
655-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_29_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=True, right=False, shape=(6, 3, 3)}::test_digitize
656-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_2_{bins=[1.5, 2.5, 4.0, 6.0], increasing=True, right=True, shape=(6, 3, 3)}::test_digitize
657-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_30_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=False, right=True, shape=()}::test_digitize
658-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_31_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=False, right=True, shape=(10,)}::test_digitize
659-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_32_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=False, right=True, shape=(6, 3, 3)}::test_digitize
660-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_33_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=False, right=False, shape=()}::test_digitize
661-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_34_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=False, right=False, shape=(10,)}::test_digitize
662-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_35_{bins=[0.0, 1.0, 1.0, 4.0, 4.0, 10.0], increasing=False, right=False, shape=(6, 3, 3)}::test_digitize
663-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_3_{bins=[1.5, 2.5, 4.0, 6.0], increasing=True, right=False, shape=()}::test_digitize
664-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_4_{bins=[1.5, 2.5, 4.0, 6.0], increasing=True, right=False, shape=(10,)}::test_digitize
665-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_5_{bins=[1.5, 2.5, 4.0, 6.0], increasing=True, right=False, shape=(6, 3, 3)}::test_digitize
666-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_6_{bins=[1.5, 2.5, 4.0, 6.0], increasing=False, right=True, shape=()}::test_digitize
667-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_7_{bins=[1.5, 2.5, 4.0, 6.0], increasing=False, right=True, shape=(10,)}::test_digitize
668-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_8_{bins=[1.5, 2.5, 4.0, 6.0], increasing=False, right=True, shape=(6, 3, 3)}::test_digitize
669-
tests/third_party/cupy/statistics_tests/test_histogram.py::TestDigitize_param_9_{bins=[1.5, 2.5, 4.0, 6.0], increasing=False, right=False, shape=()}::test_digitize
670-
671616
tests/third_party/cupy/statistics_tests/test_order.py::TestOrder::test_percentile_defaults[linear]
672617
tests/third_party/cupy/statistics_tests/test_order.py::TestOrder::test_percentile_defaults[lower]
673618
tests/third_party/cupy/statistics_tests/test_order.py::TestOrder::test_percentile_defaults[higher]

0 commit comments

Comments
 (0)