我试图将一个范围的数字转换为另一个,保持比率。数学不是我的强项。
I have an image file where point values may range from -16000.00 to 16000.00 though the typical range may be much less. What I want to do is compress these values into the integer range 0-100, where 0 is the value of the smallest point, and 100 is the value of the largest. All points in between should keep a relative ratio even though some precision is being lost I'd like to do this in python but even a general algorithm should suffice. I'd prefer an algorithm where the min/max or either range can be adjusted (ie, the second range could be -50 to 800 instead of 0 to 100).
我写了一个函数用R来做这个,方法和上面一样,但是我需要在R中做很多次,所以我想分享一下,以防它对任何人有帮助。
convertRange <- function(
oldValue,
oldRange = c(-16000.00, 16000.00),
newRange = c(0, 100),
returnInt = TRUE # the poster asked for an integer, so this is an option
){
oldMin <- oldRange[1]
oldMax <- oldRange[2]
newMin <- newRange[1]
newMax <- newRange[2]
newValue = (((oldValue - oldMin)* (newMax - newMin)) / (oldMax - oldMin)) + newMin
if(returnInt){
return(round(newValue))
} else {
return(newValue)
}
}
使用Numpy和interp函数,你可以将你的值从旧范围转换为新范围:
>>> import numpy as np
>>> np.interp(0, [-16000,16000], [0,100])
50.0
你也可以尝试映射一个值列表:
>>> np.interp([-16000,0,12000] ,[-16000,16000], [0,100])
array([ 0. , 50. , 87.5])
NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
或者更容易读懂:
OldRange = (OldMax - OldMin)
NewRange = (NewMax - NewMin)
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
或者如果你想保护旧范围为0的情况(OldMin = OldMax):
OldRange = (OldMax - OldMin)
if (OldRange == 0)
NewValue = NewMin
else
{
NewRange = (NewMax - NewMin)
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
}
注意,在这种情况下,我们被迫任意选择一个可能的新范围值。根据上下文,明智的选择可能是:NewMin(见示例),NewMax或(NewMin + NewMax) / 2
我在一个用js解决的问题中使用了这个解决方案,所以我想我将分享翻译。谢谢你的解释和解决方案。
function remap( x, oMin, oMax, nMin, nMax ){
//range check
if (oMin == oMax){
console.log("Warning: Zero input range");
return None;
};
if (nMin == nMax){
console.log("Warning: Zero output range");
return None
}
//check reversed input range
var reverseInput = false;
oldMin = Math.min( oMin, oMax );
oldMax = Math.max( oMin, oMax );
if (oldMin != oMin){
reverseInput = true;
}
//check reversed output range
var reverseOutput = false;
newMin = Math.min( nMin, nMax )
newMax = Math.max( nMin, nMax )
if (newMin != nMin){
reverseOutput = true;
};
var portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
if (reverseInput){
portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);
};
var result = portion + newMin
if (reverseOutput){
result = newMax - portion;
}
return result;
}