python - 测量 xy 点的时间序列之间的相关性 - python
问题描述
我的目标是返回一个描述 xy 点时间序列之间同步的连续测量。使用下面,有两个单独的点 ( A,B
)。它们在前 3 个时间步长上朝着相似的方向移动,而在后 3 个时间步长上则朝着不同的方向移动。
本质上,它们在时间步长上遵循相同的方向1-3
,然后在时间步长上分叉以完全不同的方向移动4-6
在单独测量单个时间序列(x 坐标或 y 坐标)之间的同步性时,有几个选项。但我找不到同时考虑两个轴(x 和 y)的函数或算法。
我可以使用pearsonr
or 一个crosscorr
函数,但它必须独立测量 x 或 y 轴。不是xy坐标在一起。
我可以使用运动的角度吗?我希望可以将预期的输出附加到表示移动点同步的每个时间点的数据帧。
注意:我希望输出是连续的和数字的(浮点数最有意义)。我在下面插入了两个不同的选项。然而,点可以沿相似的方向(但不相同)或完全不同的路径移动。输出应该处理这个。
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}")
预期输出:
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
解决方案
我不完全确定我做对了。
如果我按照您的示例进行操作,那么如果步骤之间的轨迹相同,则您的点被认为是同步的。
如果是这样,我会这样做(请注意,您对arctan2函数犯了一个错误,它首先需要 Y args)。
df[['move_x', 'move_y']] = df.groupby('Label')[['x', 'y']].diff().fillna(0)
df['Rotation'] = np.arctan2(df['move_y'], df['move_x'])
df['Angle'] = np.degrees(df['Rotation'])
temp = df.pivot_table('Angle', index="Time", columns="Label")
temp['same_direction'] = temp.eq(temp.iloc[:, 0], axis=0).all(1)
temp.drop(['A', 'B'], axis=1, inplace=True)
df.set_index('Time', inplace=True)
df = df.join(temp)
df.reset_index(drop=False, inplace=True)
df.drop(['move_x', 'move_y'], axis=1, inplace=True)
print(df)
返回:
Time Label x y Rotation Angle same_direction
0 1 A -2.0 -2.0 0.000000 0.0 True
1 1 B -1.0 -1.0 0.000000 0.0 True
2 2 A -1.0 -2.0 0.000000 0.0 True
3 2 B 0.0 -1.0 0.000000 0.0 True
4 3 A 0.0 -2.0 0.000000 0.0 True
5 3 B 1.0 -1.0 0.000000 0.0 True
6 4 A 0.0 -3.0 -1.570796 -90.0 False
7 4 B 1.0 0.0 1.570796 90.0 False
8 5 A 0.0 -4.0 -1.570796 -90.0 False
9 5 B 1.0 1.0 1.570796 90.0 False
10 6 A 0.0 -5.0 -1.570796 -90.0 False
11 6 B 1.0 2.0 1.570796 90.0 False
编辑
正如我之前所说,我不会关注你的这些评论。但是,如果您想坚持 [0;pi[ 象限中的方向并添加一个度偏差的容差,我认为您可以通过这种方式更改过程:
df[['move_x', 'move_y']] = df.groupby('Label')[['x', 'y']].diff().fillna(0)
df['Rotation'] = np.arctan2(df['move_y'], df['move_x'])
df['Angle'] = np.degrees(df['Rotation'])
temp = df.pivot_table('Rotation', index="Time", columns="Label")
#get back in the [0;pi[ quadrant :
temp = np.abs(temp).replace(np.pi, 0)
temp['MeanAngle'] = np.arctan2(np.mean(np.sin(temp), axis=1), np.mean(np.cos(temp), axis=1)) #compute mean angle at each step
temp = np.degrees(temp) #convert to degrees
THRESHOLD = .5 #tolerance of 1 degree equals to a tolerance to .5 degree to the mean angle
temp['ALMOST_SYNC'] = False
ix = temp[
(np.abs(temp.MeanAngle - temp.A < THRESHOLD))
& (np.abs(temp.MeanAngle - temp.B < THRESHOLD))
].index
temp.loc[ix, 'ALMOST_SYNC'] = True
temp.drop(['A', 'B', 'MeanAngle'], axis=1, inplace=True)
df.set_index('Time', inplace=True)
df = df.join(temp)
df.reset_index(drop=False, inplace=True)
df.drop(['move_x', 'move_y'], axis=1, inplace=True)
print(df)
返回
Time Label x y Rotation Angle ALMOST_SYNC
0 1 A -2.0 -2.0 0.000000 0.0 True
1 1 B -1.0 -1.0 0.000000 0.0 True
2 2 A -1.0 -2.0 0.000000 0.0 True
3 2 B 0.0 -1.0 0.000000 0.0 True
4 3 A 0.0 -2.0 0.000000 0.0 True
5 3 B 1.0 -1.0 0.000000 0.0 True
6 4 A 0.0 -3.0 -1.570796 -90.0 True
7 4 B 1.0 0.0 1.570796 90.0 True
8 5 A 0.0 -4.0 -1.570796 -90.0 True
9 5 B 1.0 1.0 1.570796 90.0 True
10 6 A 0.0 -5.0 -1.570796 -90.0 True
11 6 B 1.0 2.0 1.570796 90.0 True
编辑2:
对于某种线性度量,您可以在所有角度和平均角度上使用最大增量(有两个点,这将等同于最小值,顺便说一句):
df[['move_x', 'move_y']] = df.groupby('Label')[['x', 'y']].diff().fillna(0)
df['Rotation'] = np.arctan2(df['move_y'], df['move_x'])
df['Angle'] = np.degrees(df['Rotation'])
temp = df.pivot_table('Rotation', index="Time", columns="Label")
#get back in the [0;pi[ quadrant :
temp = np.abs(temp).replace(np.pi, 0)
cols = temp.columns.tolist()
temp['MeanAngle'] = np.arctan2(np.mean(np.sin(temp), axis=1), np.mean(np.cos(temp), axis=1)) #compute mean angle at each step
temp = np.degrees(temp) #convert to degrees
temp['MAX_DELTA'] = np.max(
(np.array([np.abs(temp[f] - temp['MeanAngle']) for f in cols]).T),
axis=1)
temp.drop(['A', 'B', 'MeanAngle'], axis=1, inplace=True)
df.set_index('Time', inplace=True)
df = df.join(temp)
df.reset_index(drop=False, inplace=True)
df.drop(['move_x', 'move_y'], axis=1, inplace=True)
print(df)
返回:
Time Label x y Rotation Angle MAX_DELTA
0 1 A -2.0 -2.0 0.000000 0.0 0.0
1 1 B -1.0 -1.0 0.000000 0.0 0.0
2 2 A -1.0 -2.0 0.000000 0.0 0.0
3 2 B 0.0 -1.0 0.000000 0.0 0.0
4 3 A 0.0 -2.0 0.000000 0.0 0.0
5 3 B 1.0 -1.0 0.000000 0.0 0.0
6 4 A 0.0 -3.0 -1.570796 -90.0 0.0
7 4 B 1.0 0.0 1.570796 90.0 0.0
8 5 A 0.0 -4.0 -1.570796 -90.0 0.0
9 5 B 1.0 1.0 1.570796 90.0 0.0
10 6 A 0.0 -5.0 -1.570796 -90.0 0.0
11 6 B 1.0 2.0 1.570796 90.0 0.0
推荐阅读
- python - 将 API 的响应保存到 csv 文件
- server-side-rendering - 在 SvelteKit 中解释 SSR
- ios - 如何在 Xcode 上打印指南针方向?
- kubernetes - 如何创建一个卷以挂载其路径在 ConfigMap 中配置的文件
- php - 在“woocommerce_quantity_input”可插入函数中获取产品 ID
- sql - 在 SQL 中创建动态日期范围
- java - 刷新活动
- javascript - 我想在useEffect react Js中使用带有foreach的axios,但它给了我(无法读取属性Symbol(Symbol.iterator)错误?
- go - 如何检查 Go 包文件(.a 文件)?
- javascript - 一次使用 Angular ngFor 循环遍历 JSON 数组项