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

2025-04-16 08:57:00
admin
原创
19
摘要:问题描述:我正在寻找如何在 Python 中将一个范围值转换为另一个范围值的方法。我正在做一个硬件项目,正在从一个可以返回一系列值的传感器读取数据,然后使用这些数据来驱动一个需要不同范围值的执行器。例如,假设传感器返回的值在 1 到 512 之间,而执行器由 5 到 10 之间的值驱动。我想要一个函数,可以传...

问题描述:

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

例如,假设传感器返回的值在 1 到 512 之间,而执行器由 5 到 10 之间的值驱动。我想要一个函数,可以传递一个值和两个范围,并返回映射到第二个范围的值。如果有一个这样的函数,translate可以像这样使用:

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

在这个例子中,我期望输出actuator_value是,7.5因为sensor_value位于可能的输入范围的中间。


解决方案 1:

使用 scipy.interpolate.interp1d

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

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

或者将其从 0 阶 scipy 数组转换回普通浮点数:

>>> float(m(256))
7.4951076320939336

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

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

另外,您还可以从一个范围到另一个范围进行非统一映射,例如,如果要将 [1,128] 映射到 [1,10],将 [128,256] 映射到 [10,90],将 [256,512] 映射到 [90,100],您可以这样做:

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

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

使用 numpy.interp

正如~unutbu所指出的,numpy.interp这也是一种选择(依赖性较少):

>>> from numpy import interp
>>> interp(256,[1,512],[5,10])
7.4951076320939336

解决方案 2:

一种解决方案是:

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)

您可以使用代数来使其更高效,但牺牲可读性。

解决方案 3:

这实际上是创建闭包的一个很好的例子,即编写一个返回函数的函数。由于你可能有很多这样的值,因此为每个值计算并重新计算这些值的范围和因子几乎没有意义,更不用说一直传递这些最小/最大限制了。

相反,尝试这样做:

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:

我在 python 中寻找同样的东西,将角度 0-300 度映射到原始 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:

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:

简单地图范围函数:

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

解决方案 7:

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_

  • 不将转换后的值限制在范围内ab(它进行推断)

  • 也适用于from_lower > from_upperto_lower > to_upper

解决方案 8:

所有现有答案均遵循 CC BY-SA 许可。这是我写的一个;在法律允许的范围内,我放弃此代码的所有版权或相关及邻接权利。(知识共享 CC0 公共领域贡献)。

def remap(number, from_min, from_max, to_min, to_max):                         
    number_s = number - from_min
    from_max_s = from_max - from_min
    to_max_s = to_max - to_min
    return ((number_s / from_max_s) * to_max_s) + to_min

解决方案 9:

v是值。将a-b范围映射到c-d范围

def map_range(v, a, b, c, d):
       return (v-a) / (b-a) * (d-c) + c

用法

a = map_range(4, 0, 10, 0, 1)
print(a) # -> 0.4

解决方案 10:

您可以使用 lambda 函数

translate = lambda a, b, c, d, e: (a - b) * (e - d) / (c - b) + d
sensor_value = 256
translate(sensor_value, 1, 512, 5, 10)
>> 7.495107632093934
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用