4

Is there an easy way to calculate the derivative of non-liner functions that are give by data?

for example:

x = 1 / c(1000:1)

y = x^-1.5
ycs = cumsum(y)

plot (x, ycs, log="xy")

How can I calculate the derivative function from the function given by ´x´ and ´ycs´?

R_User
  • 10,682
  • 25
  • 79
  • 120

4 Answers4

15

Was also going to suggest an example of a smoothed spline fit followed by prediction of the derivative. In this case, the results are very similar to the diff calculation described by @dbaupp:

spl <- smooth.spline(x, y=ycs)
pred <- predict(spl)

plot (x, ycs, log="xy")
lines(pred, col=2)

ycs.prime <- diff(ycs)/diff(x)
pred.prime <- predict(spl, deriv=1)

plot(ycs.prime)
lines(pred.prime$y, col=2)
Marc in the box
  • 11,769
  • 4
  • 47
  • 97
  • This answer is wrong. Try: `x=-10:10 y=x^2 plot(x, y, type = 'l', col='blue', ylim=c(-10,10)) lines(x = x, y = c(NA, diff(y)/diff(x)), type = 'l', col='red') abline(v=0, h=0) abline(a = 0, b = 2)` – Elad663 Apr 15 '18 at 19:18
  • @Elad663 - This is due to the resolution of your data. Try: `x=seq(-10,10,length.out = 100)`. – Marc in the box Apr 16 '18 at 06:04
  • @Elad663 - Actually, you didn't even use my suggested solution of a spline. This works OK even with your limited dataset: `spl <- smooth.spline(x, y=y); lines(x=x, y=predict(spl, deriv=1)$y)` – Marc in the box Apr 16 '18 at 06:14
  • a spline is a way to go, if the user understand its uncertainty. About diff(y)/diff(x), if OP is talking about a derivative from given data, you cannot assume you have nice data. – Elad663 Apr 17 '18 at 18:32
9

Generating derivatives from raw data is risky unless you are very careful. Not for nothing is this process known as "error multiplier." Unless you know the noise content of your data and take some action (e.g. spline) to remove the noise prior to differentiation, you may well end up with a scary curve indeed.

Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73
8

The derivative of a function is dy/dx, which can be approximated by Δy/Δx, that is, "change in y over change in x". This can be written in R as

ycs.prime <- diff(ycs)/diff(x)

and now ycs.prime contains an approximation to the derivative of the function at each x: however it is a vector of length 999, so you will need to shorten x (i.e. use x[1:999] or x[2:1000]) when doing any analysis or plotting.

huon
  • 94,605
  • 21
  • 231
  • 225
3

There is also gradient from the pracma package.

grad <- pracma::gradient(ycs, h1 = x)
plot(grad, col = 1)
Tony Ladson
  • 3,539
  • 1
  • 23
  • 30