处理 pandas 中值的换行

Handling wrapping of values in pandas

我正在处理来自以 angular 坐标(俯仰、滚动和偏航)报告的位置传感器的数据。传感器读数使得最大读数为 180 度。超过这一点,读数就会跳到负数。例如,一系列轻微振荡的读数可能如下所示:

 178.8
 178.9
-178.8
-178.0
-179.0
 180.0
 179.0

我目前正在通过循环检查所有值来处理这个问题。我得到两个连续读数之间的增量,并保持 运行 总数以获得我当前的 angular 位置。如果我从第三象限(90 <= 先前值 <= 180)进入第四象限(-180 <= 当前值 <= -90),我在获取增量之前将 360 添加到当前值。如果我要从第四象限进入第三象限,我会在计算增量之前减去 360。例如:

    Yaw = inData['Yaw']
    cum_sum = Yaw[0]
    for i in range(1, Yaw)):
        x_prev = Yaw[i-1]
        x = Yaw[i]
        if 90 <= x_prev and x_prev <= 180 and -180 <= x and x <= -90:
            x = x + 360
        elif -180 <= x_prev and x_prev <= -90 and 90 <= x and x <= 180:
            x = x - 360
        else:
            pass
        delta = x - x_prev
        cum_sum += delta

这里,inData 是一个包含来自多个轴的 angular 个位置的数据框,'Yaw' 是该数据框中的一个系列。

如果我可以对角度值进行一致的校正,我可以生成一系列增量并进行累加求和以获得位置。但是,将 360 添加到所有读数或使用角度作为模 360 只会将翻转点从 +/-180 之间的交叉点移动到 0 和 360 之间的交叉点。

鉴于我已经在 DataFrame/Series 中阅读了这些资料,我想知道是否有更 Pythonic(和更快)的方法来做到这一点。

全部矢量化,所以应该很快。

s = pd.Series([-178.8, 178.9, -178., -179., 180., 179.])

delta = (s.diff() + 
         (((s.shift() >= 90) & (s <= -90)).astype(int) - 
          ((s.shift() <= -90) & (s >= 90)).astype(int)) * 360)

>>> delta.cumsum()
0    NaN
1   -2.3
2    0.8
3   -0.2
4   -1.2
5   -2.2
dtype: float64

关于逻辑,如果测量值位于左上象限,((s.shift() >= 90) & (s <= -90)).astype(int) 将计算为 1,否则计算为零。如果测量值位于右下象限,-((s.shift() <= -90) & (s >= 90)).astype(int) 将计算为负一,否则计算为零。这是一种矢量化的方式,表示如果您在左上象限,则应将差值加上 360,如果您在右下象限,则应从差值中减去 360,否则只取差值。

如果我理解你的话,象限是这样的(顺时针方向):

  • 第一:-90 到 0 度。
  • 第 2:从 0 到 90 度
  • 第三:从 90 度到 180 度。
  • 第 4:从 -180 度到 90 度。

如果是这样的话,我建议您先将您的讲座转换为常规的 360 度测量:

def parseSensorReading(readingDegrees):
    if readingDegrees < 0:
        degrees360 = readingDegrees + 360
    degrees360 = readingDegrees
    return degrees360

然后检测您正在阅读的象限:

def getQuadrant(degrees360):
    if degrees360 < 360:
        quadrant = 1
    if degrees360 < 270:
        quadrant = 4
    if degrees360 < 180:
        quadrant = 3
    if degrees360 < 90:
        quadrant = 2
    return quadrant

有了象限,现在你可以计算增量了:

def getDelta(x_old, x_new):
    q_old = getQuadrant(x_old)
    q_new = getQuadrant(x_new)
    if q_old == 1 and q_new == 2:
        delta = (x_new + 360) - x_old
    else:
        delta = x_new - x_old

最后,您的代码变为:

yaw = inData["Yaw"]
cumSum = yaw[0]
for i in range(1, len(yaw) + 1)):
    x_old = parseSensorReading(yaw[i-1])
    x_new = parseSensorReading(yaw[i])
    delta = getDelta(x_old, x_new)
    cumSum += delta

注意:我更改了 for 循环中的 "range" 表达式,因为它使用列表 "yaw" 作为它的第二个参数。我假设您想说 len(yaw) + 1,所以 "i" 获取从 1 到 len(yaw) 的值。

我认为 np.unwrap() 可以做您想做的事,而不必弄乱增量和累积总和。 Docs

In [120]: data = pd.Series([178.8, 178.9, -178.8, -178.0, -179.0, 180.0, 179.0])

In [121]: np.degrees(np.unwrap(np.radians(data)))
Out[121]: array([ 178.8,  178.9,  181.2,  182. ,  181. ,  180. ,  179. ])

它处理多个环绕:

In [124]: np.degrees(np.unwrap(np.radians(data + 540)))
Out[124]: array([ 718.8,  718.9,  721.2,  722. ,  721. ,  720. ,  719. ])