title: Interpolate missing values in a time series with a seasonal cycle
body: <p>I have a time series for which I want to intelligently interpolate the missing values. The value at a particular time is influenced by a multi-day trend, as well as its position in the daily cycle. </p>
  
  <p>Here is an example in which the tenth observation is missing from <code>myzoo</code></p>
  
  <pre><code>start &lt;- as.POSIXct("2010-01-01") 
  freq &lt;- as.difftime(6, units = "hours") 
  dayvals &lt;- (1:4)*10 
  timevals &lt;- c(3, 1, 2, 4) 
  index &lt;- seq(from = start, by = freq, length.out = 16)
  obs &lt;- (rep(dayvals, each = 4) + rep(timevals, times = 4))
  myzoo &lt;- zoo(obs, index)
  myzoo[10] &lt;- NA
  </code></pre>
  
  <p>If I had to implement this, I'd use some kind of weighted mean of close times on nearby days, or add a value for the day to a function line fitted to the larger trend, but I hope there already exist some package or functions that apply to this situation?</p>
  
  <p>EDIT: Modified the code slightly to clarify my problem. There are <code>na.*</code> methods that interpolate from nearest neighbors, but in this case they do not recognize that the missing value is at the time that is the lowest value of the day. Maybe the solution is to reshape the data to wide format and then interpolate, but I wouldn't like to completely disregard the contiguous values from the same day. It is worth noting that <code>diff(myzoo, lag = 4)</code> returns a vector of 10's. The solution may lie with some combination of <code>reshape</code>, <code>na.spline</code>, and <code>diff.inv</code>, but I just can't figure it out.</p>
  
  <p>Here are three approaches that don't work:
  <img src="https://i.stack.imgur.com/xm05G.jpg" alt="enter image description here"></p>
  
  <p>EDIT2. Image produced using the following code.</p>
  
  <pre><code>myzoo &lt;- zoo(obs, index)
  myzoo[10] &lt;- NA # knock out the missing point
  plot(myzoo, type="o", pch=16) # plot solid line
  points(na.approx(myzoo)[10], col = "red")
  points(na.locf(myzoo)[10], col = "blue")
  points(na.spline(myzoo)[10], col = "green")
  myzoo[10] &lt;- 31 # replace the missing point
  lines(myzoo, type = "o", lty=3, pch=16) # dashed line over the gap
  legend(x = "topleft", 
         legend = c("na.spline", "na.locf", "na.approx"), 
         col=c("green","blue","red"), pch = 1)
  </code></pre>