Here are some approaches. We first define the input x
.
# test input
x <- data.frame(data = 1:3)
nr <- nrow(x)
# use if
for(i in 1:nr) {
dx <- data[i] - (if (i == 1) 0 else x$data[i-1])
print(dx)
}
or use an if
this way:
for(i in 1:nr) {
dx <- if (i == 1) x$data[1] else x$data[i] - data[i-1]
print(dx)
}
or use the fact that x$data[0] is zero length so c(x$data[0], 0)
equals 0:
for(i in 1:nr) {
dx <- x$data[i] - c(x$data[i-1], 0)[1]
print(dx)
}
or maintain the previous value:
prev <- 0
for(i in 1:nr) {
dx <- x$data[i] - prev
print(dx)
prev <- x$data[i]
}
A variation of this which eliminates the use of indexes is:
prev <- 0
for(xdata in x$data) {
dx <- xdata - prev
print(dx)
prev <- xdata
}
Another possibility is to handle the first iteration separately from the loop:
dx <- x$data[1]
print(dx)
for(i in 2:nr) {
dx <- x$data[i] - x$data[i-1]
print(dx)
}
or expand x$data
xdata <- c(0, x$data)
for(i in 2:length(xdata)) {
dx <- xdata[i] - xdata[i-1]
print(dx)
}
or use Reduce
junk <- Reduce(function(x, y) { print(y-x); y }, init = 0, x$data)
Alternately, note that the dx
values could be represented as a vector
c(x$data[1], diff(x$data))
or
diff(c(0, x$data))
Also note that 1:nr
only works as expected if nr >= 1. To be able to handle the edge case nr = 0 use seq_len(nr)
in place of 1:nr
. Also instead of 2:nr
use seq(2, length = nr - 1)
to handle a similar edge case.