19

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]

2 Answers 2

24

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)))
Sign up to request clarification or add additional context in comments.

1 Comment

But be careful with np.interp. From documentation, "Does not check that the x-coordinate sequence xp is increasing. If xp is not increasing, the results are nonsense."
4

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.