Pure NumPy solution using np.digitize
:
import numpy as np
scores = [95, 100, 80, 42, 39, 96, 80, 69]
bins = [64, 66, 69, 72, 76, 79, 82, 86, 89, 92, 96, 100]
gpa_scale = np.array([0.0, 1.0, 1.3, 1.7, 2.0, 2.3, 2.7, 3.0, 3.3, 3.7, 4.0, 4.0])
print(repr(gpa_scale[np.digitize(scores, bins, right=True)]))
Output:
array([4. , 4. , 2.7, 0. , 0. , 4. , 2.7, 1.3])
EDIT:
You can alternatively use np.searchsorted
, which should be a faster since it does less checks on the inputs, the code is almost identical:
import numpy as np
scores = [95, 100, 80, 42, 39, 96, 80, 69]
bins = [64, 66, 69, 72, 76, 79, 82, 86, 89, 92, 96, 100]
gpa_scale = np.array([0.0, 1.0, 1.3, 1.7, 2.0, 2.3, 2.7, 3.0, 3.3, 3.7, 4.0, 4.0])
print(repr(gpa_scale[np.searchsorted(bins, scores, side='left')]))
Output:
array([4. , 4. , 2.7, 0. , 0. , 4. , 2.7, 1.3])
Complexity:
Both np.digitize
and np.searchsorted
applies binary search to bin values, which results in a O(nlogm)
worst case complexity. Whereas for loops and if checks has a O(nm)
worst case complexity. Here n
is the length of inputs, and m
is the length of bins.