Numerical second order differentiation

I have written a code for the second differentiation of numerical list

diff2list = {}; diff2 = ConstantArray[0, {Length@firstlist, 2}];
Do[

diff2[[i]] = (firstlist[[i - 1, 2]] - 2 firstlist[[i, 2]] + firstlist[[i + 1, 2]])/(2*0.4);

AppendTo[diff2list, {0.4*i, diff2[[i]]}]

, {i, 2, Length@firstlist - 1}]

How can I change my code to be more efficient for larger lists and small intervals. The firstlist can be generated as below:

firstlist = Table[{0.4 i, N@Cos[\[Pi]/7 i]}, {i, 1, 30}];

However, my list is different from this one.

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/(#[] - #[])} & @@ 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]
• You are completely right – Inzo Babaria Jun 14 at 7:21
• Or Nest[Differences, myList, 2] if you want to do it all at once. – Michael Seifert Jun 14 at 18:54

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.