R中缺失数据的线性插值

Linear interpolation for missing data in R

我有一个数据集,记录了不同条件下的瞳孔大小。正如预期的那样,数据中存在眨眼伪影(表现为眨眼开始期间瞳孔大小值的极度下降和眼睛完全闭合时的“-1”,随后瞳孔大小再次逐渐增加)。

据我所知,基于眨眼开始前后的值对眨眼伪像进行线性插值是一种可以接受的平滑瞳孔大小数据中眨眼的方法。

示例数据:

df<-structure(list(Pupil_Avg = c(8.984, 8.984, 8.988001, 8.988001, 
8.978001, 8.978001, 8.9780005, 8.9780005, 8.9780005, 8.9780005, 
8.9780005, 8.9800005, 8.981, 8.9810005, 8.979, 8.979, 8.979, 
8.979, 8.979, 8.979, 8.979, 8.979, 8.979, 8.979, 8.9750005, 8.964, 
8.964001, 8.9660005, 8.9650005, 8.964001, 8.9610005, 8.9620005, 
8.9630005, 8.9630005, 8.963001, 8.963001, 8.96, 8.96, 8.9600005, 
8.962, 8.962, 8.969001, 8.9730005, 8.9670005, 8.9610005, 8.9610005, 
8.9610005, 8.9610005, 8.9610005, 8.9520005, 8.949001, 8.9450005, 
8.9450005, 8.9400005, 8.933001, 8.938001, 8.9510005, 8.956001, 
8.956001, 8.956001, 8.956001, 8.956001, 8.943001, 8.9280005, 
8.9280005, 8.9280005, 8.9280005, 8.9280005, 8.9350005, 8.9470005, 
8.95, 8.9530005, 8.957001, 8.9480005, 8.946, 8.944, 8.944, 8.9460005, 
8.9460005, 8.9480005, 8.9440005, 8.941, 8.938, 8.9280005, 8.9280005, 
8.9280005, 8.9280005, 8.9280005, 8.9280005, 8.929, 8.929, 8.9280005, 
8.9280005, 8.9210005, 8.918, 8.919, 8.92, 8.92, 8.92, 8.9170005, 
8.9100005, 8.9100005, 8.92, 8.9220005, 8.9220005, 8.9100005, 
8.9100005, 8.912, 8.912, 8.912, 8.912, 8.912, 8.9340005, 8.9610005, 
8.958001, 8.985, 8.978, 8.9880005, 8.9880005, 9.014, 9.014, 9.014, 
9.014, 9.014, 8.9740005, 8.9520005, 8.789, 8.6460005, 8.471001, 
8.326, 8.129001, 7.862, 7.862, 7.862, 7.862, 7.862, 7.862, 7.174, 
6.6910005, 6.518, 2.461, 2.182, 1.942, 1.942, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1.487, -1, 
-1, -1, -1, 2.202, 2.202, 2.281, 2.344, 6.265, 6.378, 6.4910005, 
6.8980005, 6.925, 7.04, 7.591, 7.7900005, 7.8470005, 7.978001, 
7.978001, 7.978001, 7.978001, 7.978001, 8.159, 8.1300005, 8.154, 
8.227, 8.281, 8.3160005, 8.353, 8.4430005, 8.4970005, 8.4970005, 
8.4970005, 8.4970005, 8.5150005, 8.6390005, 8.9930005, 9.0110005, 
9.0330005, 9.035, 9.0360005), BLINK_IDENTIFICATION = c(NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Blink Onset", NA, NA, 
NA, "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
"Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", 
NA, "Eye Closed", "Eye Closed", "Eye Closed", "Eye Closed", "Blink Offset", 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-651L))

如您在 BLINK_IDENTIFICATION 列中所见,眨眼的开始(第 141 行)和偏移(第 615 行)已被识别。闭眼时(Pupil_Avg 列中的 -1)也已在这些标签之间识别出来。

我的主要目标是根据眨眼开始和结束前后的值,线性插值从 "blink onset" 到 "offset" 之后 x 次观察的数据。

任何人都可以建议一种方法吗? R 中似乎有各种插值函数(例如,approx())。我只是不是 100% 确定如何实施它们。理想情况下,我想尽可能避免使用 for loop,因为我的完整数据集有数百万行长,但如果没有其他方法,我将使用 for 循环。

编辑:这是一个使用上述数据集对眨眼进行插值的函数示例:

install.packages("zoo")
library('zoo')
library(dplyr)

# replace every '-1' value with 'NA'
df$Pupil_Avg[df$Pupil_Avg == -1] <- NA

df<-df%>%mutate(approx = na.approx(Pupil_Avg))

以上结果是从第一个闭眼开始的插值(Pupil_Avg 列中的 NA)。这是一个开始,但我需要插值从 "Blink Onset" 之前的行开始,如前所述。

感谢您的宝贵时间。

你可以这样做:

library("imputeTS")
onset <- which("Blink Onset" == df$BLINK_IDENTIFICATION)[[1]]
offset <- which("Blink Offset" == df$BLINK_IDENTIFICATION)[[1]]

df$BLINK_IDENTIFICATION[onset:offset] <- -1
df$Pupil_Avg[df$BLINK_IDENTIFICATION == -1] <- NA
df <- na.interpolation(df$Pupil_Avg, option ="linear")

如果您的时间序列中恰好有 1 blink_onset 和偏移量,则此方法有效。如果您的系列中有多个,只需删除 which 函数中的 [[1]],然后您将获得所有事件的列表。然后,您使用这两个出现向量将系列的相应部分设置为 NA。

该示例现在使用 imputeTS 的插值函数代替 zoo。两者都可以完成工作。 imputeTS 的功能稍微快一些,但其他代码可能会占用大部分计算时间。您可以将选项设置为 "spline" 和 "stine" 以从线性插值更改为样条插值或 Stineman 插值。 (na.spline 如果您使用的是动物园)