2

I am trying to integrate the difference in a stepwise function and a continuous function, but the value I am getting is as if the step-wise function were identically zero, which I know it is not. Here is my code

NumLessThan[x_, data_] := (i = 1; 
  For[i := 1, x > Sort[data][[i]] && i <= Length[data], ,If[++i > Length[data], Break[]]]; i - 1)    
CDFDisc[x_, data_] := NumLessThan[x, Sort[data]]/Length[data]

data = 
 RandomVariate[NormalDistribution[], 
  2]; Plot[{CDF[NormalDistribution[], x], CDFDisc[x, data]}, {x, -5, 
  4}]

NIntegrate[
 Abs[CDF[NormalDistribution[], x] - CDFDisc[x, data]], {x, -10, 10}]
(* 10. *)

Plot[
 Abs[CDF[NormalDistribution[], x] - CDFDisc[x, data]], {x, -10,
   10}, PlotRange -> Full]

NIntegrate[CDF[NormalDistribution[], x], {x, -10, 10}]
(* 10. *)

I am aware that my discrete CDF function is algorithmically terrible, but I am just trying to get it to work before I make it computationally more optimal. The function CDFDisc outputs the correct values. And when I plot the integrand, I get exactly what I would expect. The mystery is why, inside NIntegrate it is treating CDFDisc as if it were zero everywhere.

xzczd
  • 65,995
  • 9
  • 163
  • 468
irh
  • 123
  • 5
  • 1
    I think you are looking for CDF[EmpiricalDistribution[data], x] – rhermans Jun 20 '18 at 15:14
  • Cool, of course Mathematica has a built in function for this. Thank you. Do you have any ideas why what I did breaks though? For some reason NIntegrate thinks my CDFDisc is zero, and I can't figure out why. In addition to getting this specific example working I want to get an understanding of how what I did is wrong. – irh Jun 20 '18 at 15:18
  • 1
    Because Mathematica it's trying to be clever and solve the integral analytically first. Use x_?NumericQ to force a numerical only interpretation. – rhermans Jun 20 '18 at 15:26
  • Thank you so much. I think your last comment just clarified a lot about how Mathematica works, and cleared up a lot of frustration/confusion. – irh Jun 20 '18 at 15:30
  • While the underlying principal might be the same, had I read that question before reading your answer to mine, I would not have realized they were related. Just saying, having them both online might provide future value to confused noobs like myself. – irh Jun 20 '18 at 15:38
  • You need to add @xzczd in your comment or I won't get the reminder. Posts marked as duplicate won't be removed, they'll exist as root signs (and kind of supplement), so don't worry :) . – xzczd Jun 20 '18 at 15:42

1 Answers1

3

rhermans has already suggested a better way for coding CDFDisc, here I'll just explain why your CDFDisc seems to be zero. It's because:

  1. Though NIntegrate has the attribute HoldAll, it symbolically evaluates its integrand before integrates it. See this post for more information.

  2. CDFDisc[x, data] evaluates to 0 as long as x is a symbol.

So, once again, a straightforward way to fix your code is adding _?NumericQ to CDFDisc:

CDFDisc // Clear
CDFDisc[x_?NumericQ, data_] := ……

BTW the following is another way to define CDFDisc:

CDFDisc[x_] = 
 Simplify`PWToUnitStep@
  Piecewise[{Range@Length@data/Length@data, x > # & /@ Sort[data]}\[Transpose] // 
    Reverse]
xzczd
  • 65,995
  • 9
  • 163
  • 468
  • Figuring out how your CDFDisc function works has taught me so much about MMA. Thank you. The part I still don't understand is the Simplify\PWToUnitStep@` at the beginning, as I can't find PWToUnitStep in any documentation, although it is clear I think what the effect is. – irh Jun 20 '18 at 18:47
  • @irh Yeah it's not documented but as you've noticed its usage is pellucid and is briefly introduced in this post. It's actually not necessary for defining CDFDisc, I add it because piecewise function defined with UnitStep is usually more efficient and convenient for numeric calculation. This function is also used in dozens of posts in this site, you may have a look: https://mathematica.stackexchange.com/search?q=Simplify%5C%60PWToUnitStep – xzczd Jun 21 '18 at 00:34