4
$\begingroup$

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.

$\endgroup$
6
$\begingroup$

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]]}
$\endgroup$
5
$\begingroup$

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]
$\endgroup$
  • $\begingroup$ You are completely right $\endgroup$ – Inzo Babaria Jun 14 at 7:21
  • $\begingroup$ Or Nest[Differences, myList, 2] if you want to do it all at once. $\endgroup$ – Michael Seifert Jun 14 at 18:54
5
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.