组内插值

时间:2014-04-27 16:51:46

标签: r interpolation plyr

目标

我想在数据帧中的组内插值。这将为数据帧中的每个组提供任意数量的中间点。

最小工作示例

我有一个类似的数据框:

OldDataFrame <- data.frame(ID   = c(1,1,1,2,2,2),
                           time = c(1,2,3,1,2,3),
                           Var1 = c(-0.6 , 0.2, -0.8 , 1.6 , 0.3 , -0.8),
                           Var2 = c(0.5 , 0.7, 0.6 , -0.3 , 1.5 , 0.4) )

我想得到一个像这样的函数:

TimeInterpolateByGroup <- function(DataFrame, 
                                   GroupingVariable, 
                                   TimeVariable,
                                   TimeInterval){
  #Something Here
}

如果我不必指定列来执行此操作,它会很方便,它可以在numcolwise

中的plyr等每个数字列上自动运行

这样我就可以这样申请:

NewDataFrame = TimeInterpolateByGroup(DataFrame         = OldDataFrame,
                                      GroupingVariable  = "ID",
                                      TimeVariable      = "time",
                                      TimeInterval      = 0.25)

将NewDataFrame设为:

NewDataFrame = data.frame(ID    =   c(  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2   ),
                          time  =   c(  1,  1.25,   1.5,    1.75,   2,  2.25,   2.5,    2.75,   3,  1,  1.25,   1.5,    1.75,   2,  2.25,   2.5,    2.75,   3   ), 
                           Var1 =   c(  -0.6,   -0.4,   -0.2,   0,  0.2,    -0.05,  -0.3,   -0.55,  -0.8,   1.6,    1.275,  0.95,   0.625,  0.3,    0.025,  -0.25,  -0.525, -0.8    ), 
                           Var2 =   c(  0.5,    0.55,   0.6,    0.65,   0.7,    0.675,  0.65,   0.625,  0.6,    -0.3,   0.15,   0.6,    1.05,   1.5,    1.225,  0.95,   0.675,  0.4 ))

或以图片形式我想:

enter image description here

没有相关问题的相关问题

Interpolate variables on subsets of dataframe

  • 使用plyr类型的方法似乎是在正确的方向,但有一个令人困惑的例子,没有能够拥有任意数量的中间插值点。这对于动画应用程序很重要(见下文),我不知道在获得平滑动画时需要多少个中间时间点。

其他一些答案使用时间序列方法但不允许按组进行分段。

我还考虑过使用纵向数据包,但对于应该是一个简单的问题来说,这似乎不必要地复杂化。

期望的申请

我希望得到一个Var1和Var2的x-y图,其中每个ID点的时间点为1.然后我想使用animate包来看到随着时间的增加点移动。为了顺利完成这项工作,我需要及时为中间点设置所有坐标。

2 个答案:

答案 0 :(得分:3)

我非常确定下面的代码给出了正确的答案,除了由于使用approx()函数导致的微小数值不精确。基本思想是使用ddply来分割和组合数据帧,并使用近似进行插值。

library(plyr)

# time_interpolate is a helper function for TimeInterpolateByGroup
# that operates on each of the groups. In the input to this function,
# the GroupingVariable column of the data frame should be single-valued.
# The function returns a (probably longer) data frame, with estimated
# values for the times specified in the output_times array.
time_interpolate <- function(data_frame,
                             GroupingVariable,
                             time_var,
                             output_times) {
  input_times <- data_frame[, time_var]
  exclude_vars <- c(time_var, GroupingVariable)
  value_vars <- setdiff(colnames(data_frame), exclude_vars)
  output_df <- data.frame(rep(data_frame[1,GroupingVariable], length(output_times)), output_times)
  colnames(output_df) <- c(GroupingVariable, time_var)
  for (value_var in value_vars) {
    output_df[,value_var] <- approx(input_times, data_frame[, value_var], output_times)$y
  }
  return(output_df)
}

# A test for time_interpolate
time_interpolate(OldDataFrame[1:3,], "ID" , "time", seq(from=1, to=3, by=0.25))

TimeInterpolateByGroup <- function(DataFrame, 
                                   GroupingVariable, 
                                   TimeVariable,
                                   TimeInterval){
  min_time <- min(DataFrame[, TimeVariable])
  max_time <- max(DataFrame[, TimeVariable])
  output_times <- seq(from=min_time, to=max_time, by=TimeInterval)
  ddply(DataFrame,
        GroupingVariable,
        time_interpolate,
        GroupingVariable=GroupingVariable,
        time_var=TimeVariable,
        output_times=output_times)
}

答案 1 :(得分:3)

您也可以使用na.approx包中的zoo

library(zoo)
my_fun <- function(DataFrame, GroupingVariable, TimeVariable, TimeInterval){
  do.call(rbind, by(DataFrame, DataFrame[ , GroupingVariable], function(dat){
    tt <- data.frame(time = seq(from = min(dat[ , TimeVariable]),
                                to = max(dat[ , TimeVariable]),
                                by = TimeInterval))
    dat2 <- merge(tt, dat, all.x = TRUE)
    na.approx(dat2)
  }))
}

my_fun(df, "ID", "time", 0.25)