代码之家  ›  专栏  ›  技术社区  ›  Tendayi Mawushe

将一系列值映射到另一个值

  •  48
  • Tendayi Mawushe  · 技术社区  · 15 年前

    我正在寻找有关如何在Python中将一个范围值转换为另一个范围值的想法。我正在进行硬件项目,从一个传感器读取数据,该传感器可以返回一个数值范围,然后我使用该数据驱动一个需要不同数值范围的执行器。

    translate

    sensor_value = 256
    actuator_value = translate(sensor_value, 1, 512, 5, 10)
    

    在本例中,我希望输出 actuator_value 成为 7.5 sensor_value 在可能的输入范围的中间。

    5 回复  |  直到 15 年前
        1
  •  108
  •   Adam Luchjenbroers    15 年前

    一种解决办法是:

    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)
    

        2
  •  99
  •   sastanin    15 年前

    使用scipy.interpolate.interp1d

    你也可以使用 scipy.interpolate 包进行此类转换(如果您不介意依赖于SciPy):

    >>> from scipy.interpolate import interp1d
    >>> m = interp1d([1,512],[5,10])
    >>> m(256)
    array(7.4951076320939336)
    

    >>> float(m(256))
    7.4951076320939336
    

    您还可以在一个命令中轻松地执行多个转换:

    >>> m([100,200,300])
    array([ 5.96868885,  6.94716243,  7.92563601])
    

    作为奖励,您可以从一个范围到另一个范围进行非均匀映射,例如,如果您想将[1128]映射到[1,10]、[128256]映射到[10,90]和[256512]映射到[90100],您可以这样做:

    >>> m = interp1d([1,128,256,512],[1,10,90,100])
    >>> float(m(400))
    95.625
    

    interp1d 创建分段线性插值对象(与函数一样可调用)。

    正如 ~unutbu , numpy.interp

    >>> from numpy import interp
    >>> interp(256,[1,512],[5,10])
    7.4951076320939336
    
        3
  •  27
  •   PaulMcG    15 年前

    相反,请尝试以下方法:

    def make_interpolater(left_min, left_max, right_min, right_max): 
        # Figure out how 'wide' each range is  
        leftSpan = left_max - left_min  
        rightSpan = right_max - right_min  
    
        # Compute the scale factor between left and right values 
        scaleFactor = float(rightSpan) / float(leftSpan) 
    
        # create interpolation function using pre-calculated scaleFactor
        def interp_fn(value):
            return right_min + (value-left_min)*scaleFactor
    
        return interp_fn
    

    # create function for doing interpolation of the desired
    # ranges
    scaler = make_interpolater(1, 512, 5, 10)
    
    # receive list of raw values from sensor, assign to data_list
    
    # now convert to scaled values using map 
    scaled_data = map(scaler, data_list)
    
    # or a list comprehension, if you prefer
    scaled_data = [scaler(x) for x in data_list]
    
        4
  •  10
  •   Stephen Rauch Afsar Ali    7 年前

    我在python中寻找同样的东西,将角度0-300deg映射到原始dynamixel值0-1023或1023-0,具体取决于执行器方向。

    变量:

    x:input value; 
    a,b:input range
    c,d:output range
    y:return value
    

    功能:

    def mapFromTo(x,a,b,c,d):
       y=(x-a)/(b-a)*(d-c)+c
       return y
    

    dyn111.goal_position=mapFromTo(pos111,0,300,0,1024)
    
        5
  •  7
  •   inspectorG4dget Dillon Benson    15 年前
    def translate(sensor_val, in_from, in_to, out_from, out_to):
        out_range = out_to - out_from
        in_range = in_to - in_from
        in_val = sensor_val - in_from
        val=(float(in_val)/in_range)*out_range
        out_val = out_from+val
        return out_val
    
        6
  •  4
  •   Joe    5 年前
    def maprange(a, b, s):
        (a1, a2), (b1, b2) = a, b
        return  b1 + ((s - a1) * (b2 - b1) / (a2 - a1))
    
    
    a = [from_lower, from_upper]
    b = [to_lower, to_upper]
    

    发现于 https://rosettacode.org/wiki/Map_range#Python_

    • a b (它推断)
    • 也适用于 from_lower > from_upper to_lower > to_upper
        7
  •  0
  •   HariSreedhar    3 年前

    简单地图范围功能:

    def mapRange(value, inMin, inMax, outMin, outMax):
        return outMin + (((value - inMin) / (inMax - inMin)) * (outMax - outMin))