2

I am trying to convert x[0] to 0 instead of numeric(0) in R.

What I am trying to do is to have in a for loop this line of code:

dx <- x$data[i] - x$data[i - 1]

However, as soon as the loop starts I get numeric(0) as [i - 1] for the first point gives 0 which would be x[0], and when it comes to the subtraction I still get numeric(0).

I would like to convert x[0] into 0 instead of numeric(0) so that the line of code reported above would give:

dx <- x$data[i] - x$data[i - i]
dx <- x$data[i] - 0`
dx <- x$data[i]

x: is a tibble with three columns.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • 1
    Have you tried starting your loop at 1 since in R the first element is x[1] not x[0]? – Martin Gal Apr 29 '20 at 18:31
  • 1
    R uses 1-based indexes not 0-based. You cannot define a 0th element. Instead you can maybe use `if/else` or `ifelse()` or start your loop at a later value. It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input and desired output that can be used to test and verify possible solutions. – MrFlick Apr 29 '20 at 18:52
  • Or use built-in functions, sticking the 0 on the front. `dx = c(0, diff(x$data))` – Gregor Thomas Apr 29 '20 at 18:56
  • Thanks guys, I've managed to get it sorted with an if statement. Thank you very much for your help, really appreciate it! – Marco Zanin Apr 30 '20 at 14:19

1 Answers1

1

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.

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341