Wednesday, 24 February 2021

Measure correlation between a time series of xy points - python

I'm aiming to return a single continuous measurement describing the synchrony between a time series of xy points. Using below, there are two separate points (A,B). They are moving in a similar direction for the first 3 time points and in diverging directions for the last 3 time points.

In essence, they are following the same direction for time points 1-3 and then diverge to move in completely separate directions in time points 4-6

There are a few options when measuring the synchrony between a single time series in isolation (either the x-coordinate or y-coodinate). But I can't find a function or algorithm that accounts for both axes (both x and y).

I can use pearsonr or a crosscorr function but it would have to measure the x or y-axis independently. Not the xy coordinate together.

Could I use the angle of movement? I'm hoping the intended output can be appended to the data frame at each point in time that represents the synchronisation of moving points.

Note: I'm hoping to output will be continuous and numerical (float makes most sense). I have inserted two distinct options below. However points can be moving in a similar direction (but not identical) or in completely divergent paths. The output should handle this.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.DataFrame({      
    'Time' : [1,1,2,2,3,3,4,4,5,5,6,6],    
    'Label' : ['A','B','A','B','A','B','A','B','A','B','A','B'],
    'x' : [-2.0,-1.0,-1.0,0.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0],
    'y' : [-2.0,-1.0,-2.0,-1.0,-2.0,-1.0,-3.0,0.0,-4.0,1.0,-5.0,2.0],              
   })

x = df.groupby('Label')['x'].diff().fillna(0).astype(float)
y = df.groupby('Label')['y'].diff().fillna(0).astype(float) 

# Return rotation of scalar difference and convert angle
df['Rotation'] = np.arctan2(x, y)
df['Angle'] = np.degrees(df['Rotation'])

df_A = df[df['Label'] == 'A'].reset_index(drop = True)
df_B = df[df['Label'] == 'B'].reset_index(drop = True)

#rolling_corr = df_A['Angle'].rolling(1).corr(df_B['Angle'])
#print(rolling_corr)

r, p = stats.pearsonr(df_A['Angle'], df_B['Angle'])
print(f"Scipy computed Pearson r: {r} and p-value: {p}")

Intended output:

    Time Label    x    y  Rotation  Angle Corr
0      1     A -2.0 -2.0  0.000000    0.0 1.0
1      1     B -1.0 -1.0  0.000000    0.0 1.0
2      2     A -1.0 -2.0  1.570796   90.0 1.0
3      2     B  0.0 -1.0  1.570796   90.0 1.0
4      3     A  0.0 -2.0  1.570796   90.0 1.0
5      3     B  1.0 -1.0  1.570796   90.0 1.0
6      4     A  0.0 -3.0  3.141593  180.0 0.0
7      4     B  1.0  0.0  0.000000    0.0 0.0
8      5     A  0.0 -4.0  3.141593  180.0 0.0
9      5     B  1.0  2.0  0.000000    0.0 0.0
10     6     A  0.0 -5.0  3.141593  180.0 0.0
11     6     B  1.0  1.0  3.141593  180.0 0.0

enter image description here



from Measure correlation between a time series of xy points - python

No comments:

Post a Comment