You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

时间戳不匹配的眼动追踪数据相关性计算方法咨询

嘿,这个问题我之前处理过类似的生理时序信号对齐场景,确实直接用df.corr()行不通——时间戳不匹配的话,样本点对应关系就乱了,计算出来的相关性完全没意义。下面给你几个更靠谱的方案,比单纯填充NaN要贴合你的数据特性:

1. 时间对齐重采样(最推荐)

因为瞳孔大小、注视速度都是连续变化的生理指标,先把两组数据对齐到统一的时间轴上是最合理的思路。你可以用重采样+插值的方式,把不同时间戳的数据映射到相同的采样频率上:

# 假设df1、df2分别是两名受试者的数据集,包含timestamp、pupil_size、gaze_velocity列
# 先把时间戳设为索引并排序
df1 = df1.set_index('timestamp').sort_index()
df2 = df2.set_index('timestamp').sort_index()

# 取两组数据的共同时间范围,避免超出某一方的数据区间
common_start = max(df1.index.min(), df2.index.min())
common_end = min(df1.index.max(), df2.index.max())

# 重采样到统一频率(比如10ms,根据你的原始数据采样率调整),用线性插值补全缺失值
resampled_sub1 = df1.loc[common_start:common_end].resample('10ms').interpolate(method='linear')
resampled_sub2 = df2.loc[common_start:common_end].resample('10ms').interpolate(method='linear')

# 现在时间戳完全一致,直接计算相关性
pupil_corr = resampled_sub1['pupil_size'].corr(resampled_sub2['pupil_size'])
gaze_corr = resampled_sub1['gaze_velocity'].corr(resampled_sub2['gaze_velocity'])

这个方法的优势是保留了数据的时序连续性,线性插值也符合生理信号的渐变规律,不会像盲目填充NaN那样引入噪声。如果你的数据波动较大,还可以换成spline(样条插值)来更平滑地拟合。

2. 基于时间窗口的统计匹配

如果原始数据采样率极不均匀,或者你想观察不同时间尺度下的相关性,可以把时间划分为固定窗口(比如500ms/1s),计算每个窗口内的统计量(均值、中位数等),再用这些统计量来计算相关性:

# 定义一个计算窗口统计量的函数
def get_window_metrics(df, window='500ms'):
    return df.resample(window).agg({
        'pupil_size': 'mean',
        'gaze_velocity': 'median'  # 注视速度用中位数更抗噪
    })

# 对两组数据分别计算窗口指标
windowed_sub1 = get_window_metrics(df1.set_index('timestamp').sort_index())
windowed_sub2 = get_window_metrics(df2.set_index('timestamp').sort_index())

# 对齐窗口索引,只保留双方都有数据的窗口
aligned_windows = windowed_sub1.join(windowed_sub2, lsuffix='_sub1', rsuffix='_sub2', how='inner')

# 计算相关性
pupil_window_corr = aligned_windows['pupil_size_sub1'].corr(aligned_windows['pupil_size_sub2'])

这种方法适合分析“宏观趋势”的相关性,比如两名受试者在相同任务阶段的瞳孔变化是否同步。

3. 谨慎使用NaN填充(仅短时间缺失适用)

如果你坚持想用填充NaN的思路,别直接填0或者均值——这会严重扭曲数据。建议只对短时间间隔的缺失值做前向/后向填充,同时过滤掉时间间隔过大的无效样本:

# 合并两组数据,保留所有时间戳
merged_df = df1.set_index('timestamp').join(
    df2.set_index('timestamp'),
    lsuffix='_sub1', rsuffix='_sub2',
    how='outer'
).sort_index()

# 计算相邻时间戳的间隔,只填充间隔小于100ms的缺失值(阈值根据你的数据调整)
time_diff = merged_df.index.to_series().diff().dt.total_seconds()
merged_df['pupil_size_sub1'] = merged_df['pupil_size_sub1'].where(
    time_diff > 0.1, merged_df['pupil_size_sub1'].ffill()
)
merged_df['pupil_size_sub2'] = merged_df['pupil_size_sub2'].where(
    time_diff > 0.1, merged_df['pupil_size_sub2'].ffill()
)

# 删除仍有NaN的行,再计算相关性
clean_df = merged_df.dropna()
if not clean_df.empty:
    pupil_corr = clean_df['pupil_size_sub1'].corr(clean_df['pupil_size_sub2'])
else:
    print("有效样本不足,无法计算相关性")

这个方法只适合数据缺失是偶然的、短时间的情况,比如某几帧采样丢失,否则还是会引入虚假的相关性。


内容的提问来源于stack exchange,提问作者Tank

火山引擎 最新活动