1
$\begingroup$

I have two very connected questions:

Is there really no built-in function to integrate a list of pairs without converting to a function? Something like:

NIntegrate[{{x1, y1}, ..., {xn, yn}}]

I am aware of Interpolation, but do not want to use it.

If there is no built-in function, is there a possibility to improve my following function (I stole the important part from here)?

 rangeSelect[table_, range_] := 
   Select[table, range[[1]] <= #[[1]] <= range[[2]] &]
 trapezoidIntegration[list_, range_] := 
   Differences[#1].MovingAverage[#2, 2] & @@ Transpose[rangeSelect[list, range]]

=======1. Edit

I think I have to clarify what I intended with defining rangeSelect[matrix,{a,b}] This function should slice out all those rows from the 2D array "matrix" in the form of {{x1,y1},...,{xn,yn}} where the x value is larger than a and smaller than b.

=======2. Edit

My function introduces errors at the beginning and end of the integration interval. Since my data is automatically sampled hence has a lot of points this is not so important for me. This is also the reason, why I did not think about non integrable 1 element lists. For the same data as in m_goldberg's answer but with n=10^4 trapezoidIntegrationand Integrate[Interpolation[...]] give the same result.

$\endgroup$
  • $\begingroup$ why do you not want to use interpolate? $\endgroup$ – chris Oct 9 '15 at 18:24
  • $\begingroup$ I have experimental data and used interpolate with an Order 6. Already from the plots you see that it does not represent my data very well. $\endgroup$ – mcocdawc Oct 9 '15 at 18:27
  • $\begingroup$ In addition the normal trapezoidIntegration[] of the list gives quite a good value of the integral while NIntegrate[Inperpolation[...]] is orders of magnitude away from the literature values. $\endgroup$ – mcocdawc Oct 9 '15 at 18:29
  • $\begingroup$ Can you show a plot of your data? $\endgroup$ – J. M. will be back soon Oct 9 '15 at 18:30
  • 3
    $\begingroup$ By the way: look up InterpolationOrder. $\endgroup$ – J. M. will be back soon Oct 9 '15 at 18:30
7
$\begingroup$

I am going to argue against your rejection of using Interpoation.

Generated data

SeedRandom[42];
With[{n = 12}, data = Transpose[{Range[n] // N, RandomReal[12., n]}]];

Applying the trapezoidal rule directly gives

Total[.5 (#[[1, 2]] + #[[2, 2]]) & /@ Partition[data, 2, 1]]
55.0291

(Perhaps you can adapt this to your work if you don't buy my argument.)

First-order interpolation

dataF = Interpolation[data, InterpolationOrder -> 1];

Does dataF accurately represents the data?

Table[{i, dataF[i]}, {i, 1., 12.}] == data
True

Therefore,

NIntegrate[dataF[x], {x, 1., 12.}, 
  Method -> {"TrapezoidalRule", "RombergQuadrature" -> False}]
55.0291

And this reflects IMO good Mathematica practice for handling this kind of quadrature problem. However, with this particular generated data set, there is no reason to explicitly force the trapezoid rule because the naive evaluation

NIntegrate[dataF[x], {x, 1., 12.}]
55.0291

works just as well.

$\endgroup$
  • $\begingroup$ This also works efficiently: Integrate[dataF[x], x] /. x -> 12. $\endgroup$ – Michael E2 Oct 9 '15 at 21:19
  • $\begingroup$ @MichaelE2. Indeed, but the OP explicitly asked about applying the trapezoid rule, and I felt constrained to stick with that. $\endgroup$ – m_goldberg Oct 9 '15 at 21:26
  • 2
    $\begingroup$ I'm pretty sure Integrate uses the trapezoid rule, if InterpolationOrder is 1. And it's quite a bit faster than the NIntegrate alternative you propose. $\endgroup$ – Michael E2 Oct 9 '15 at 22:22
8
$\begingroup$

First, the answer to the OP's question about a built-in function is given here:

It says since version 6, one should use Integrate with Interpolation like this:

Integrate[Interpolation[data, InterpolationOrder ->k], {x, a, b}]

where k = 1 in this case. In other words the old built-in ListIntegrate, which used to do what the OP desires, has been decommissioned.


Using m_goldberg's data, ListCorrelate, slightly modified from belisarius's answer to Is it possible to compute with the trapezoidal rule by numerical integration?, is the fastest alternative I've found:

SeedRandom[42];
With[{n = 12}, data = Transpose[{Range[n] // N, RandomReal[12., n]}]];

1/2 Differences[data[[All, 1]]]. ListCorrelate[{1, 1}, data[[All, 2]]]

I'm not sure what the rangeSelect is intended to do. For instance,

rangeSelect[data, {2.5, 3.5}]

results in an un-integrable list:

{{3., 4.16483}}

Similar trimming of the interval is likely for any call to rangeSelect, although one may get a list of length greater than one:

rangeSelect[data, {2.5, 4.5}]
(*  {{3., 4.16483}, {4., 5.44489}}  *)

If the integral over the interval {2.5, 3.5} of the trapezoidal approximation is intended, then we can apply Integrate as recommended in the documentation:

dataF = Interpolation[data, InterpolationOrder -> 1];
Integrate[dataF[x], {x, 2.5, 3.5}]

(again using m_goldberg's data and interpolation dataF).

$\endgroup$

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