使用样条插值并保持精确的打结值

时间:2015-11-24 21:51:33

标签: r interpolation spline

问题

我正在玩样条曲线,试图连接中期几个月,从1月15日开始插入整年;但是,我想确保全年正确设置中点月份。也就是说,在每个月我都希望中间点(第15个)与原始月度数据相同。目前,我的代码没有这样做,有些值与原始代码有很大不同。如果可能的话,我想确保那些确切的值适合每月中点(15日)的数据。

有没有办法确保原始数据中的这些点在插值数据中正确设置,以便它们位于每月中点(第15位)的确切位置?

示例:

# Monthly data
df <- data.frame(x <- seq(1,12), 
                 y <- c(45, 54, 50 ,63, 70, 75, 80, 88, 76, 81, 63, 54))

# Interpolate with spline to daily data starting with 15th of January (351 days)
values <- spline(df$x, df$y, n = 351)$y

# Check values
# Original values
df$y

# New values at 15th of each month
values[c(1,31, 60,91,121,152,182,213,244,274,305,335)]

输出(有些圆形,但大多数已关闭):

> df$y
 [1] 45 54 50 63 70 75 80 88 76 81 63 54

> values[c(1,31, 60,91,121,152,182,213,244,274,305,335)]
 [1] 45.00000 54.21321 49.65891 60.61385 68.91151 73.89644 77.62606 87.33305 79.66860 79.27115 73.10543 54.71480

期望的输出:

    > df$y
     [1] 45 54 50 63 70 75 80 88 76 81 63 54

    > values[c(1,31, 60,91,121,152,182,213,244,274,305,335)]
     [1] 45 54 50 63 70 75 80 88 76 81 63 54

图片:

红色:原始月份

黑线:样条插值的点

2 个答案:

答案 0 :(得分:2)

如果您尝试将日历与日历日对齐,则可以让R执行跟踪日期的工作。这种方法也将照顾闰年。最后,您可以从1月15日开始按日编制索引。以今年为例,代码可能如下所示:

  df <- data.frame(x=seq.Date(as.Date("2015-01-15"), by="month", length.out=12), 
                   y = c(45, 54, 50 ,63, 70, 75, 80, 88, 76, 81, 63, 54))
   values_by_date <- splinefun(df$x, df$y)
#
# To get a value at every day between Jan 15 and Dec 15
#
 values <- values_by_date(seq.Date(df$x[1], tail(df$x,1), by="day"))
#
#  Check dates at mid month
#  Note that second index should be 32, not 31
#
 values[c(1,32, 60,91,121,152,182,213,244,274,305,335)]

[1] 45 54 50 63 70 75 80 88 76 81 63 54

答案 1 :(得分:1)

也许它比WaltS提供的答案更复杂,但它确实有效:

# Input data:
df <- data.frame(x <- seq(1,12),
                 y <- c(45, 54, 50 ,63, 70, 75, 80, 88, 76, 81, 63, 54))
# I use this dataframe to get the right position for the ticks
# The "offset_days" column is left 'empty' at start:
days_of_month <- data.frame(months=c('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'),
                            days = c(31,28,31,30,31,30,31,31,30,31,30,31),
                            offset_days = 0)
# Offset: The day of month you want your ticks to be placed (should be between 1 and 28):
offset <- 15

# Fill the "offset_days" column with the appropriate day
for(i in 1:nrow(days_of_month)) {
  if(i == 1)
    days_of_month$offset_days[i] <- offset
  else
    days_of_month$offset_days[i] <- days_of_month$offset_days[i-1] + days_of_month$days[i-1]
}

# Calculate the spline with the offset days as x value:
sp <- spline(days_of_month$offset_days, df$y, 351)

plot(sp$x, sp$y, type='l', xlim=c(0,365), xaxt='n')
lines(days_of_month$offset_days, df$y, type='o', col='red')
axis(side=1, at=cumsum(days_of_month$days), lab=rep('',12))
axis(side=1, at=days_of_month$offset_days, lab=days_of_month$months, tck=0)

输出:

Output

红线表示原始数据,黑线表示平滑数据。

希望这有帮助