角度插值

时间:2017-03-09 13:02:10

标签: python

我试图插入列表中的角度。

Dir DirOffset
0   109.6085
30  77.5099
60  30.5287
90  -10.2748
120 -75.359
150 -147.6015
180 -162.7055
210 21.0103
240 3.5502
270 -11.5475
300 -39.8371
330 -109.5473
360 109.6085

enter image description here

我已经编写了插入角度的代码(它继续计算角度之间的平均值以达到插值),这需要很长时间。如果有人有更快更短的代码,请帮助我。

enter image description here

from cmath import rect, phase
from math import radians, degrees, sqrt

#Calculate the mean of angles in List
def mean_angle(degArray):
    return degrees(phase(sum(rect(1, radians(d)) for d in degArray)/len(degArray)))

#Calculate Interpolation Angle
def Interpolate_angle(Dir, DirOffset, ValuetoInterpolate):
    #Create Lower and Higher bin of ValuetoInterpolate
    DirLBin = round(float(ValuetoInterpolate)/30,0)*30
    DirHBin = round(float(ValuetoInterpolate+15)/30,0)*30

    #Check if the ValuetoInterpolate lies between Lower and Higher bin
    if DirLBin == DirHBin:
        DirLBin = DirHBin-30
        if DirLBin <= ValuetoInterpolate <= DirHBin:
            DBin = [float(DirLBin), float(DirHBin)]
            Doff = [DirOffset[Dir.index(DirLBin)], DirOffset[Dir.index(DirHBin)]] 
        else:
            DirHBin = DirLBin+30
            DBin = [float(DirLBin), float(DirHBin)]
            Doff = [DirOffset[Dir.index(DirLBin)], DirOffset[Dir.index(DirHBin)]] 

    else:
        DBin = [float(DirLBin), float(DirHBin)]
        Doff = [DirOffset[Dir.index(DirLBin)], DirOffset[Dir.index(DirHBin)]]

    #Run 50 iterations to calculate the mean of angle and find the ValuetoInterpolate    
    for i in range(51):
        DMean = mean_angle(DBin)
        DOMean = mean_angle(Doff)
        if DMean < 0 :
            DMean = 360+DMean

        if DBin[0] <= ValuetoInterpolate <=DMean:
            DBin = [float(DBin[0]), float(DMean)]
            Doff = [float(Doff[0]), float(DOMean)]
        else:
            DBin = [float(DMean), float(DBin[1])]
            Doff = [float(DOMean), float(Doff[1])] 

    return DOMean

Dir = range(0,370,30)
DirOffset = [109.6085,77.5099,30.5287,-10.2748,-75.359,-147.6015,-162.7055,21.0103,3.5502,-11.5475,-39.8371,-109.5473,109.6085]
ValuetoInterpolate = 194.4
print Interpolate_angle(Dir, DirOffset, ValuetoInterpolate)

2 个答案:

答案 0 :(得分:2)

在从stackoverflow中搜索答案后,我得到了上述问题的解决方案,然后我根据我的要求进行了一点修改以获得解决方案。该解决方案可能对某些需要它的人有用。

我使用以下函数为每个方向bin(0,30,60 .... 360)插入度数直到360(360和0度将相同)并将它们存储在字典中以创建DataFrame(pandas DataFrame)并将其与主DataFrame连接并进一步处理。

enter image description here

def InterpolateDegrees(109.6085,77.5099)

将返回DirectionOffset的插值数组0到30度,间隔为0.1(0.0,0.1,0.2,0.3 ...... 28.7,29.8,29.9)

import numpy as np
from math import fabs

def InterpolateDegrees(start, end, BinSector=12):
    BinAngle = 360/BinSector
    amount = np.arange(0,1,(1/(BinAngle/0.1)))
    dif = fabs(end-start)
    if dif >180:
        if end>start:
            start+=360
        else:
            end+=360

    #Interpolate it
    value = (start + ((end-start)*amount))

    #Wrap it
    rzero = 360

    Arr = np.where((value>=0) & (value<=360), (value), (value % rzero))
    return Arr

答案 1 :(得分:1)

这是一个基于 Pandas/Numpy 的解决方案,用于使用 NaN 数据对角度序列进行插值。

import pandas as pd
import numpy as np

def interpolate_degrees(series: pd.Series) -> pd.Series:
    # I don't want to modify in place 
    series = series.copy()
    
    # convert to radians
    a = np.radians(series)
    
    # unwrap if not nan
    a[~np.isnan(a)] = np.unwrap(a[~np.isnan(a)])
    series.update(a)
    
    # interpolate unwrapped values
    interpolated = series.interpolate()
    
    # wrap 0 - 360 (2*pi)
    wrapped = (interpolated + 2*np.pi) % (2 * np.pi)
    
    # cconvert back to degrees
    degrees = np.degrees(wrapped)
    series.update(degrees)
    return series

用法:

angle = [350, np.nan, 355, np.nan, 359, np.nan, 1, np.nan, 10]
df = pd.DataFrame(data=angle, columns=['angle'])

df['interpolated'] = interpolate_degrees(df.angle)

example output