Numerical second order differentiation
You can use the two argument form of Differences
(Differences[list, n]
) to get nth differences:
Transpose[{firstlist[[2 ;; -2, 1]],
Differences[firstlist[[All, 2]], 2] / 2 / {-1, 1}.firstlist[[{1, 2}, 1]]}]
% == diff2list
True
Or make it a function:
ClearAll[diF2]
diF2 = Transpose[{Most@Rest@#, Differences[#2, 2]/2/(#[[2]] - #[[1]])} & @@ Transpose@#] &;
diF2 @ firstlist == diff2list
True
You can also use the following alternatives to Differences[lst, 2]
:
ListConvolve[{1., -2., 1.}, lst]
ListCorrelate[{1., -2., 1.}, lst]
{1, -2, 1}.{lst[[1 ;; -3]], lst[[2 ;; -2]], lst[[3 ;; -1]]}
I'm pretty sure you've been trained in a language other than Mathematica because your style and syntax take advantage of none of Mathematica's unique power:
myList = RandomInteger[{0, 5}, 10];
diff2 = Differences[myList];
diff3 = Differences[diff2]
If you have to take the differences often, it may pay off to assemble a SparseArray
that does it for you:
n = 1000000;
A = Plus[
DiagonalMatrix[SparseArray@ConstantArray[-2., n]],
DiagonalMatrix[SparseArray@ConstantArray[1., n - 1], 1],
DiagonalMatrix[SparseArray@ConstantArray[1., n - 1], -1]
][[2 ;; -2]];
myList = RandomReal[{-1, 1}, n];
a = Differences[myList, 2]; // RepeatedTiming // First
b = Subtract[myList[[1 ;; -3]] + myList[[3 ;; -1]], 2. myList[[2 ;; -2]]]; // RepeatedTiming // First
c = A.myList; // RepeatedTiming // First
a == b == c
0.0268
0.0064
0.0038
True
I also suggest to keep the list of x- and y-values apart as two vectors of length $n$ (rather than muddling them to gether to a $n \times 2$ matrix); that will quicken the read operations that you will most likely perform on the data.