2
$\begingroup$

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.

$\endgroup$
6
  • 1
    $\begingroup$ I think you are looking for CDF[EmpiricalDistribution[data], x] $\endgroup$
    – rhermans
    Jun 20, 2018 at 15:14
  • $\begingroup$ 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. $\endgroup$
    – irh
    Jun 20, 2018 at 15:18
  • 1
    $\begingroup$ Because Mathematica it's trying to be clever and solve the integral analytically first. Use x_?NumericQ to force a numerical only interpretation. $\endgroup$
    – rhermans
    Jun 20, 2018 at 15:26
  • $\begingroup$ 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. $\endgroup$
    – irh
    Jun 20, 2018 at 15:30
  • $\begingroup$ 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. $\endgroup$
    – irh
    Jun 20, 2018 at 15:38

1 Answer 1

3
$\begingroup$

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]
$\endgroup$
2
  • $\begingroup$ 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. $\endgroup$
    – irh
    Jun 20, 2018 at 18:47
  • $\begingroup$ @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: mathematica.stackexchange.com/… $\endgroup$
    – xzczd
    Jun 21, 2018 at 0:34

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