用 R 中分组数据的线性回归预测值填充 NA 值

fill in NA values with predicted values from linear regression for grouped data in R

我想在 prop_below5 变量中为那些我没有使用线性插值进行测量的深度 (depth_round) 填充 NA,并在可用时保留实际测量值。我想对每个 Cruise/Cast 数据组进行线性回归。

当我对选择第一个 Cruise 和 Cast 的数据进行子集化并应用 lm()predict() 时,我得到了正确的值:

OS2017 <- data[data$Cruise=="OS1701" & data$Cast==1,]
OS2017$prop_below5_interp <- ifelse(is.na(OS2017$prop_below5), predict(lm(OS2017$prop_below5 ~ OS2017$depth_round), OS2017), OS2017$prop_below5)
head(OS2017)

  Cruise Cast depth_round prop_below5 prop_below5_interp
1 OS1701    1           0          NA         0.04478375
2 OS1701    1           1  0.04142012         0.04142012
3 OS1701    1           2          NA         0.04351924
4 OS1701    1           3          NA         0.04288698
5 OS1701    1           4          NA         0.04225472
6 OS1701    1           5          NA         0.04162247

当我尝试在 dplyr 中实现这个以对每个 Cruise/Cast 组做同样的事情时,我没有得到相同的答案...

data <- data %>% group_by(Cruise, Cast) %>% mutate(prop_below5_interp=ifelse(is.na(prop_below5), predict(lm(prop_below5 ~ depth_round,.), .), prop_below5))
data <- as.data.frame(data)
head(data)

  Cruise Cast depth_round prop_below5 prop_below5_interp
1 OS1701    1           0          NA         0.29926186
2 OS1701    1           1  0.04142012         0.04142012
3 OS1701    1           2          NA         0.29258267
4 OS1701    1           3          NA         0.28924308
5 OS1701    1           4          NA         0.28590349
6 OS1701    1           5          NA         0.28256390
> 

如何在 dplyr 内正确执行此操作?

这里是一段数据:

structure(list(Cruise = c("OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", "OS1701", 
"OS1701", "OS1701", "OS1701", "OS1701", "OS1701"), Cast = c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 4L, 
4L, 4L, 4L), depth_round = c(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 
21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 
34L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 42L, 43L, 44L, 45L, 46L, 
47L, 48L, 49L, 50L, 51L, 52L, 0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 
8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 
21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 
34L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 42L, 0L, 1L, 2L, 3L), 
    prop_below5 = c(NA, 0.0414201183431953, NA, NA, NA, NA, NA, 
    NA, NA, NA, 0.0436507936507936, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, 0.0296803652968037, 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, 0.4, NA, NA)), row.names = c(53L, 
33L, 48L, 36L, 51L, 38L, 23L, 12L, 4L, 43L, 31L, 41L, 46L, 49L, 
45L, 35L, 9L, 50L, 25L, 26L, 40L, 14L, 42L, 52L, 44L, 30L, 19L, 
16L, 5L, 1L, 10L, 7L, 18L, 17L, 8L, 32L, 20L, 34L, 11L, 21L, 
2L, 24L, 15L, 6L, 3L, 47L, 22L, 39L, 37L, 13L, 27L, 28L, 29L, 
84L, 58L, 85L, 86L, 93L, 89L, 75L, 77L, 91L, 66L, 67L, 81L, 82L, 
54L, 92L, 71L, 95L, 61L, 63L, 73L, 87L, 74L, 62L, 64L, 65L, 56L, 
60L, 59L, 70L, 72L, 96L, 88L, 76L, 90L, 79L, 78L, 80L, 94L, 57L, 
55L, 68L, 69L, 83L, 98L, 99L, 126L, 134L), class = "data.frame")
> 

如果您的问题是“为什么 dplyr 不起作用”,我帮不了您。但是使用 data.table.

可以轻松实现您的要求
library(data.table)
setDT(df)
#   count of non-NA values by group
df[, N:=sum(!is.na(prop_below5)), by=.(Cruise, Cast)]
#   need at least 2 non-NA values or lm will fail
df[N > 1
   , interp:=predict(lm(prop_below5~depth_round, data=.SD[!is.na(prop_below5)]), newdata=.SD)
   , by=.(Cruise, Cast)]

上面的代码识别 non-NA 值不足以使用 lm(...) 的组,然后在可能的组上运行 interpolation/extrapolation。在您提供的数据中,除第一个组之外的所有组都具有 0 或 1 non-NA 值。