R 中数据帧的(线性)插值(ddply)

(Linear) Interpolation in R for data frame (ddply)

我需要从 5 年的时间间隔内插年度数据,到目前为止,我找到了如何使用 approx() 对一次观察进行插值。但是我有一个大数据集,当我尝试使用 ddply() 来申请每一行时,无论我在最后一行代码中尝试什么,我都会收到错误消息。

例如:

   town <- data.frame(name = c("a","b","c"), X1990 = c(100,300,500), X1995=c(200,400,700))
   d1990 <-c(1990)
   d1995 <-c(1995)
   town_all <- cbind(town,d1990,d1995)


    library(plyr)
    Input <- data.frame(town_all)
    x <- c(town_all$X1990, town_all$X1995)
    y <- c(town_all$d1990, town_all$d1995)
    approx_frame <- function(df) (approx(x=x, y=y, method="linear", n=6, ties="mean"))
    ddply(Input, town_all$X1990, approx_frame)

另外,如果知道什么函数计算几何插值就好了。 (我只能找到样条或常量方法的示例。)

我会先将数据放入长格式(每列对应一个变量,所以一列用于 'year',一列用于 'value')。然后,我使用 data.table,但可以使用 dplyr 或其他 split-apply-combine 方法采用相同的方法。此 interp 函数旨在使用为每个间隔计算的恒定速率进行几何插值。

## Sample data (added one more year)
towns <- data.frame(name=c('a', 'b', 'c'),
                    x1990=c(100, 300, 500),
                    x1995=c(200, 400, 700),
                    x2000=c(555, 777, 999))

## First, transform data from wide -> long format, clean year column
library(data.table)                                                        # or use reshape2::melt
towns <- melt(as.data.table(towns), id.vars='name', variable.name='year')  # wide -> long
towns[, year := as.integer(sub('[[:alpha:]]', '', year))]                      # convert years to integers

## Function to interpolate at constant rate for each interval
interp <- function(yrs, values) {
    tt <- diff(yrs)               # interval lengths
    N <- head(values, -1L)     
    P <- tail(values, -1L)
    r <- (log(P) - log(N)) / tt   # rate for interval
    const_rate <- function(N, r, time) N*exp(r*(0:(time-1L)))
    list(year=seq.int(min(yrs), max(yrs), by=1L),
         value=c(unlist(Map(const_rate, N, r, tt)), tail(P, 1L)))
}

## geometric interpolation for each town
res <- towns[, interp(year, value), by=name]

## Plot
library(ggplot2)
ggplot(res, aes(year, value, color=name)) +
    geom_line(lwd=1.3) + theme_bw() +
    geom_point(data=towns, cex=2, color='black') +  # add points interpolated between
    scale_color_brewer(palette='Pastel1')