Reputation: 94
I would like to compute the speed from data in xts
time series. My data looks like this (command bellow generates sample, actual data is much larger).
measurement <- xts(c(7.9, 8.6, 12.7, 13.3),
as.POSIXct(c("2016-02-24 06:00:00",
"2016-02-24 07:30:00",
"2016-02-24 09:15:00",
"2016-02-24 11:15:00")))
names(measurement) <- "pos"
head(measurement)
pos
2016-02-24 06:00:00 7.9
2016-02-24 07:30:00 8.6
2016-02-24 09:15:00 12.7
2016-02-24 11:15:00 13.3
If I use diff
I am getting the changes between successive values.
diff(measurement)
pos
2016-02-24 06:00:00 NA
2016-02-24 07:30:00 0.7
2016-02-24 09:15:00 4.1
2016-02-24 11:15:00 0.6
However, I would like to take time into account and compute speed (e.g. change in time period). I have tried using the following dirty road.
measurement$time <- as.numeric(index(measurement))
measurement$speed <- diff(measurement$pos) / diff(measurement$time) * 3600
head(measurement)
pos time speed
2016-02-24 06:00:00 7.9 1456290000 NA
2016-02-24 07:30:00 8.6 1456295400 0.4666667
2016-02-24 09:15:00 12.7 1456301700 2.3428571
2016-02-24 11:15:00 13.3 1456308900 0.3000000
There must be a simpler and more elegant way to do this. Have in mind that I am still new to R and might be missing something.
Upvotes: 2
Views: 2495
Reputation: 5530
I'm not aware that either base R or the xts
package provides a way to directly calculate a physical rate in the way you're doing. A bit more straightforward way to do the speed
calculation in hours might be
# alternative time conversion
del_t <- diff(index(measurement))
units(del_t) <- "hours"
measurement$speed_hr <- diff(measurement$pos, na.pad=FALSE)/as.numeric(del_t)
The units of time returned by diff
can be specified so in this case can be set to hours
.
More generally, your speed calculation has discontinuities at the data points. In some situations, there would also be a requirement for continuity of speed
across the data points. speed
could then be calculated using R's splinefun
routine which can return not only the spline interpolation for position but also the first derivative giving an approximation of speed which is both continuous and depends upon more than two of neighboring data points. Code could look like
# provides continuity of speed at data points
# perform cubic spline fit
spline_fit <- splinefun(x=index(measurement), y=measurement$pos, method="natural")
# add spline speeds to measurements
measurement$spline_spd <- spline_fit(index(measurement), deriv=1)*3600
The spline speeds disagree with the speeds from the original calculation but this seems to be a result of the constraint on continuity at the data points. A plot may help to clarify this.
# make a sequence of plot times for spline fits
spline_times <- seq(start(measurement), end(measurement), length.out=40)
# plot positions
par(mfcol=c(2,1))
plot(spline_times, spline_fit(spline_times, deriv=0), col="red", type="b",
main="Positions", xlab = "Time", ylab="Pos")
points(index(measurement), measurement$pos, type="p", pch=19, cex=1.1)
legend("topleft", legend = c("-- pos data","-- spline pos interpolations"),
text.col = c("black","red"), y.intersp=.2, yjust=3., bty="n", cex=1.3)
# plot speeds
plot(spline_times, spline_fit(spline_times, deriv=1)*3600, col="red", type="b",
main="Speeds", xlab="Time", ylab="Speed")
lines(index(measurement), measurement$speed, type="b", pch=19, cex=1.1)
legend("topleft", legend = c("-- speed calculation","-- spline speed interpolations"),
text.col = c("black","red"), y.intersp=.2, yjust=3., bty="n", cex=1.3)
Four data points is really too few for a good spline fit but perhaps this conveys the general idea.
Upvotes: 3