Mapping a numeric range onto another
Let's forget the math and try to solve this intuitively.
First, if we want to map input numbers in the range [0
, x
] to output range [0
, y
], we just need to scale by an appropriate amount. 0 goes to 0, x
goes to y
, and a number t
will go to (y/x)*t
.
So, let's reduce your problem to the above simpler problem.
An input range of [input_start
, input_end
] has input_end - input_start + 1
numbers. So it's equivalent to a range of [0
, r
], where r = input_end - input_start
.
Similarly, the output range is equivalent to [0
, R
], where R = output_end - output_start
.
An input of input
is equivalent to x = input - input_start
. This, from the first paragraph will translate to y = (R/r)*x
. Then, we can translate the y
value back to the original output range by adding output_start
: output = output_start + y
.
This gives us:
output = output_start + ((output_end - output_start) / (input_end - input_start)) * (input - input_start)
Or, another way:/* Note, "slope" below is a constant for given numbers, so if you are calculating
a lot of output values, it makes sense to calculate it once. It also makes
understanding the code easier */
slope = (output_end - output_start) / (input_end - input_start)
output = output_start + slope * (input - input_start)
Now, this being C, and division in C truncates, you should try to get a more accurate answer by calculating things in floating-point:double slope = 1.0 * (output_end - output_start) / (input_end - input_start)
output = output_start + slope * (input - input_start)
If wanted to be even more correct, you would do a rounding instead of truncation in the final step. You can do this by writing a simple round
function:#include <math.h>
double round(double d)
{
return floor(d + 0.5);
}
Then:output = output_start + round(slope * (input - input_start))
Mapping a range of values to another
One solution would be:
def translate(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
You could possibly use algebra to make it more efficient, at the expense of readability. Javascript / jQuery - map a range of numbers to another range of numbers
You can implement this as a pure Javascript function:
function scale (number, inMin, inMax, outMin, outMax) {
return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
Use the function, like this:const num = 5;
console.log(scale(num, 0, 10, -50, 50)); // 0
console.log(scale(num, -20, 0, -100, 100)); // 150
I'm using scale
for the function name, because map
is frequently associated with iterating over arrays and objects. best way to map a value from range number in python?
Given that the ranges aren't all equal sizes (for 1-4, the range is 50, but for 5 it is 100), you could use a generator expression with sum()
like this:
def get_level_of_aqi(aqi):
return sum(l<=aqi for l in [0, 51, 101, 151, 201, 301])
This takes advantage of True
having a value of 1
and False
having a value of 0
Here are example outputs:
In [1]: get_level_of_aqi(50)
Out[1]: 1
In [2]: get_level_of_aqi(100)
Out[2]: 2
In [3]: get_level_of_aqi(125)
Out[3]: 3
In [4]: get_level_of_aqi(220)
Out[4]: 5
In [5]: get_level_of_aqi(280)
Out[5]: 5
In [6]: get_level_of_aqi(310)
Out[6]: 6
Mapping a range of values to another value
Since the ranges are consecutive, you can try to map them by the start number, and then find the value with a dichotomic search:
var map = [
[1, 49],
[10, 54],
[25, 59],
[50, 50],
[75, 49],
[100, 40],
[151, void 0]
];
function getValueInRange(arr, n, from, to) {
return (function main(from, to){
if(from>=to) return void 0;
var mid = Math.floor((from+to)/2);
if(arr[mid][0] > n) return main(from, mid);
if(arr[mid][0] < n && mid > from) return main(mid, to);
return arr[mid][1];
})(from===void 0 ? 0 : from, to===void 0 ? arr.length : to);
}
// Use it like this:
getValueInRange(map, value);
re-mapping a number to another range in pygame
Write a function which maps from a range [a, b] to a range [c, d]:
def maprange(x, a, b, c, d):
w = (x-a) / (b-a)
y = c + w * (d-c)
return y
y = maprange(25, 0, 100, 0, 20)
Related Topics
Why Can't You Add Attributes to Object in Python
Plotting Results of Hierarchical Clustering Ontop of a Matrix of Data in Python
Converting Strings to Floats in a Dataframe
Syntaxerror: Unexpected Eof While Parsing
Rename Multiindex Columns in Pandas
Pandas: Subindexing Dataframes: Copies VS Views
Splitting a String by List of Indices
Installing Pygraphviz on Windows 10 64-Bit, Python 3.6
What's the Difference Between Subprocess Popen and Call (How to Use Them)
Pandas - Filter Dataframe by Another Dataframe by Row Elements
Python - Email Header Decoding Utf-8
Why How to Not Create a Wheel in Python
How to Test a Function with Input Call
Change Tick Frequency on X (Time, Not Number) Frequency in Matplotlib