我想在数据帧中的组内插值。这将为数据帧中的每个组提供任意数量的中间点。
我有一个类似的数据框:
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 ))
Interpolate variables on subsets of dataframe
plyr
类型的方法似乎是在正确的方向,但有一个令人困惑的例子,没有能够拥有任意数量的中间插值点。这对于动画应用程序很重要(见下文),我不知道在获得平滑动画时需要多少个中间时间点。其他一些答案使用时间序列方法但不允许按组进行分段。
我还考虑过使用纵向数据包,但对于应该是一个简单的问题来说,这似乎不必要地复杂化。
我希望得到一个Var1和Var2的x-y图,其中每个ID点的时间点为1.然后我想使用animate
包来看到随着时间的增加点移动。为了顺利完成这项工作,我需要及时为中间点设置所有坐标。
答案 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)