Search code examples
pythonpandasdataframeinterpolationangle

How to interpolate data and angles with PANDAS


I have a simple dataframe df that contains three columns:

  • Time: expressed in seconds
  • A: set of values that can vary between -inf to +inf
  • B: set of angles (degrees) which range between 0 and 359

Here is the dataframe

df = pd.DataFrame({'Time':[0,12,23,25,44,50], 'A':[5,7,9,8,11,6], 'B':[300,358,4,10,2,350]})

And it looks like this:

        Time  A   B
    0   0     5   300
    1   12    7   358
    2   23    9   4
    3   25    8   10
    4   44    11  2
    5   50    6   350

My idea is to interpolate the data from 0 to 50 seconds and I was able to achieve my goal using the following lines of code:

y  = pd.DataFrame({'Time':list(range(df['Time'].iloc[0], df['Time'].iloc[-1]))})
df = pd.merge(left=y, right=df, on='Time', how='left').interpolate()

Problem: even though column A is interpolated correctly, column B is wrong because the interpolation of an angle between 360 degrees is not performed! Here is an example:

    Time       A             B
12  12  7.000000    358.000000
13  13  7.181818    325.818182
14  14  7.363636    293.636364
15  15  7.545455    261.454545
16  16  7.727273    229.272727
17  17  7.909091    197.090909
18  18  8.090909    164.909091
19  19  8.272727    132.727273
20  20  8.454545    100.545455
21  21  8.636364    68.363636
22  22  8.818182    36.181818
23  23  9.000000    4.000000

Question: can you suggest me a smart and efficient way to solve this issue and being able to interpolate correctly the angles between 0/360 degrees?


Solution

  • You should be able to use the method described in this question for the angle column:

    import numpy as np
    import pandas as pd
    
    df = pd.DataFrame({'Time':[0,12,23,25,44,50], 'A':[5,7,9,8,11,6], 'B':[300,358,4,10,2,350]})
    df['B'] = np.rad2deg(np.unwrap(np.deg2rad(df['B'])))
    y  = pd.DataFrame({'Time':list(range(df['Time'].iloc[0], df['Time'].iloc[-1]))})
    df = pd.merge(left=y, right=df, on='Time', how='left').interpolate()
    df['B'] %= 360
    print(df)
    

    Output:

        Time          A           B
    0      0   5.000000  300.000000
    1      1   5.166667  304.833333
    2      2   5.333333  309.666667
    3      3   5.500000  314.500000
    4      4   5.666667  319.333333
    5      5   5.833333  324.166667
    6      6   6.000000  329.000000
    7      7   6.166667  333.833333
    8      8   6.333333  338.666667
    9      9   6.500000  343.500000
    10    10   6.666667  348.333333
    11    11   6.833333  353.166667
    12    12   7.000000  358.000000
    13    13   7.181818  358.545455
    14    14   7.363636  359.090909
    15    15   7.545455  359.636364
    16    16   7.727273    0.181818
    17    17   7.909091    0.727273
    18    18   8.090909    1.272727
    19    19   8.272727    1.818182
    20    20   8.454545    2.363636
    21    21   8.636364    2.909091
    22    22   8.818182    3.454545
    23    23   9.000000    4.000000
    24    24   8.500000    7.000000
    25    25   8.000000   10.000000
    26    26   8.157895    9.578947
    27    27   8.315789    9.157895
    28    28   8.473684    8.736842
    29    29   8.631579    8.315789
    30    30   8.789474    7.894737
    31    31   8.947368    7.473684
    32    32   9.105263    7.052632
    33    33   9.263158    6.631579
    34    34   9.421053    6.210526
    35    35   9.578947    5.789474
    36    36   9.736842    5.368421
    37    37   9.894737    4.947368
    38    38  10.052632    4.526316
    39    39  10.210526    4.105263
    40    40  10.368421    3.684211
    41    41  10.526316    3.263158
    42    42  10.684211    2.842105
    43    43  10.842105    2.421053
    44    44  11.000000    2.000000
    45    45  11.000000    2.000000
    46    46  11.000000    2.000000
    47    47  11.000000    2.000000
    48    48  11.000000    2.000000
    49    49  11.000000    2.000000