Similar to this question, I want to fit a Numpy array into a certain range, however unlike the linked question I don't want to normalise it. How can I do this efficiently? Is there a built-in method in Numpy?
To clarify with an example, where my_scale is the function I'm looking for and out_range defines the output range:
res = my_scale(np.array([-3, -2, -1], dtype=np.float), out_range)
assert res == [-1, 0, 1]
assert res != [-1, -2/3, -1/3]
                After asking on CodeReview, I was informed there is a built-in np.interp that accomplishes this:
np.interp(a, (a.min(), a.max()), (-1, +1))
I've left my old answer below for the sake of posterity.
I made my own function based off of the D3.js code in this answer:
import numpy as np
def d3_scale(dat, out_range=(-1, 1)):
    domain = [np.min(dat, axis=0), np.max(dat, axis=0)]
    def interp(x):
        return out_range[0] * (1.0 - x) + out_range[1] * x
    def uninterp(x):
        b = 0
        if (domain[1] - domain[0]) != 0:
            b = domain[1] - domain[0]
        else:
            b =  1.0 / domain[1]
        return (x - domain[0]) / b
    return interp(uninterp(dat))
print(d3_scale(np.array([-2, 0, 2], dtype=np.float)))
print(d3_scale(np.array([-3, -2, -1], dtype=np.float)))
                        This will do the trick:
def rescale_linear(array, new_min, new_max):
    """Rescale an arrary linearly."""
    minimum, maximum = np.min(array), np.max(array)
    m = (new_max - new_min) / (maximum - minimum)
    b = new_min - m * minimum
    return m * array + b
Note that there are (infinitely) many other, nonlinear ways of rescaling an array to fit within a new range, and this choice can be important depending on the circumstances.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With