使用dplyr进行线性插值

10

我试图使用zoo库中的na.approx()函数(与xts一起)来插补多个个体的多个测量数据中的缺失值。

示例数据...

event.date <- c("2010-05-25", "2010-09-10", "2011-05-13", "2012-03-28", "2013-03-07",    
                "2014-02-13", "2010-06-11", "2010-09-10", "2011-05-13", "2012-03-28",
                "2013-03-07", "2014-02-13")
variable   <- c("neck.bmd", "neck.bmd", "neck.bmd", "neck.bmd", "neck.bmd", "neck.bmd",
                "wbody.bmd", "wbody.bmd", "wbody.bmd", "wbody.bmd", "wbody.bmd", "wbody.bmd")
value      <- c(0.7490, 0.7615, 0.7900, 0.7730, NA, 0.7420, 1.0520, 1.0665, 1.0760,
                1.0870, NA, 1.0550)
## Bind into a data frame
df <- data.frame(event.date, variable, value)
rm(event.date, variable, value)
## Convert date
df$event.date <- as.Date(df$event.date)
## Load libraries
library(magrittr)
library(xts)
library(zoo)

我可以使用xts()na.approx()为给定人员的单个结果插值一个缺失数据点....

## Subset one variable
wbody <- subset(df, variable == "wbody.bmd")
## order/index and then interpolate
xts(wbody$value, wbody$event.date) %>%
  na.approx()
2010-06-11 1.052000
2010-09-10 1.066500
2011-05-13 1.076000
2012-03-28 1.087000
2013-03-07 1.070977
2014-02-13 1.055000

虽然返回矩阵不是理想的,但我能够解决这个问题。然而,我的主要问题是对于多人有多种结果。也许有点天真,我认为既然这是一个分割-应用-合并的问题,我可以使用 dplyr 以以下方式实现...

## Load library
library(dplyr)
## group and then arrange the data (to ensure dates are correct)
df %>%
  group_by(variable) %>%
    arrange(variable, event.date) %>%
      xts(.$value, .$event.date) %>%
        na.approx()

Error in xts(., .$value, .$event.date) : order.by requires an appropriate time-based object

看起来dplyrxts/zoo不太兼容。我花了几个小时搜索如何在R中插值缺失数据点的教程/示例,但只找到了单个案例示例,到目前为止,我还无法找到任何关于如何针对多个站点和多个人进行此操作的内容(我意识到通过将我的数据重塑为宽格式,我可以将其变成一个多人问题,但这仍然无法解决我遇到的问题)。希望您能提供任何思路、建议和见解。

谢谢

编辑:澄清一些函数来自zoo包。


2
我不熟悉 xts,但也许你正在寻找这个:df %>% group_by(variable) %>% arrange(variable, event.date) %>% mutate(value = na.approx(value)),其中 na.approx 是来自于 zoo 包的。如果你想使用 dplyr 修改列,通常需要在 mutate 调用内部进行,或者如果你有任意函数,则需要在 do 调用内部进行。 - talat
据我所知,在xts中没有na.approx函数(刚刚安装了它)。 - talat
@docendodiscimus @shadow 对不起,我混淆了xtszoo的命令(在阅读xts扩展zoo中的时间序列函数时把自己搞糊涂了)。 - slackline
“Error in xts(., .$value, .$event.date)” 表明 magrittr/ dplyr. 作为 xts() 的第一个参数传递,但您真正想要的是 xts(.$value, .$event.date) - Joshua Ulrich
@JoshuaUlrich,我确实使用了“xts(.$value,.$event.date)”,但我不明白为什么它被解释为“xts(。 ,.$value,.$event.date)”。您有任何想法吗? - slackline
显示剩余5条评论
2个回答

17

使用approx()函数进行线性插值:

df %>%
  group_by(variable) %>%
    arrange(variable, event.date) %>%
    mutate(time=seq(1,n())) %>%
      mutate(ip.value=approx(time,value,time)$y) %>%
      select(-time)

使用 spline 函数进行非线性插值:

df %>%
  group_by(variable) %>%
    arrange(variable, event.date) %>%
    mutate(time=seq(1,n())) %>%
      mutate(ip.value=spline(time,value ,n=n())$y) %>%
      select(-time)

对我来说有效。我认为你不需要“排列”步骤才能正确地进行插值。 - Scrope

15

我采用的解决方案基于@docendodiscimus的第一个评论。与我之前的做法不同,这种方法通过利用dplyrmutate()函数向现有数据帧添加列。

我的代码现在是...

df %>%
  group_by(variable) %>%
    arrange(variable, event.date) %>%
      mutate(ip.value = na.approx(value, maxgap = 4, rule = 2))

maxgap 允许最多四个连续的 NA,而 rule 选项允许外推到相邻的时间点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接