jasondavies / science.js

Scientific and statistical computing in JavaScript.
http://www.jasondavies.com/
Other
886 stars 93 forks source link

Loess -- Returning NaNs. #19

Closed joearasin closed 9 years ago

joearasin commented 9 years ago

I have run into an issue with loess where, for a set of points, all the weights are becoming 0, thus leaving NaN as the result for a piece of the fit. I'm going to try to put together a simple test case.

joearasin commented 9 years ago

Ok -- found the issue. Array.prototype.sort, as called on line 117 of loess.js, sorts lexicographically by default, not numerically. Occasionally this might not be detectable, as when finding the median, plenty of values that may be randomly returned are "good enough".

slfan2013 commented 5 years ago

Hi @joearasin , is this issue fixed? Actually I still got the same issue of returning NaNs.

Please see my following code,

x = [336, 348, 359, 370, 381, 392, 403, 414, 425, 436, 447, 459, 470, 481, 492, 503, 514, 525, 535, 546, 556, 568, 579, 590, 601, 612, 623, 634, 645, 656, 667, 668, 671];
y = [74424, 80523, 76017, 79656, 80387, 85514, 83565, 82273, 85214, 85977, 71245, 73222, 70282, 73039, 75512, 108677, 83249, 83261, 85322, 85880, 82211, 89690, 85743, 83391, 85897, 106901, 108514, 110311, 89848, 89238, 90288, 96918, 94159];
weight1 = [0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1];

var loess2 = science.stats.loess(); loess2.bandwidth(0.08);
 yValuesSmoothed = loess2(x, y, weight1);

This will return all NaNs.

[NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]

Using another weight, it will return several NaNs.

x = [336, 348, 359, 370, 381, 392, 403, 414, 425, 436, 447, 459, 470, 481, 492, 503, 514, 525, 535, 546, 556, 568, 579, 590, 601, 612, 623, 634, 645, 656, 667, 668, 671];
y = [74424, 80523, 76017, 79656, 80387, 85514, 83565, 82273, 85214, 85977, 71245, 73222, 70282, 73039, 75512, 108677, 83249, 83261, 85322, 85880, 82211, 89690, 85743, 83391, 85897, 106901, 108514, 110311, 89848, 89238, 90288, 96918, 94159];
weight2 = [1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1];

var loess2 = science.stats.loess(); loess2.bandwidth(0.08);
 yValuesSmoothed = loess2(x, y, weight2);

The result is

[74424, 80523, 76017, 79656, 80387, 85514, NaN, 82273, 82273, 71245, 71245, 73222, 70282, 73039, 75512, 108677, 83249, 83261, 85322, 85880, 82211, 89690, NaN, 83391, 85897, 106901, 108514, 110311, NaN, 89238, 90288, 96918, 94159]

joearasin commented 5 years ago

Wow -- I'm probably not the right person to ask, considering this isn't my library (and I haven't looked at this code in 3.5 years, aside to fix the issue I had). My gut feeling looking at the errors you're having is that the 0-weighted points are causing something to divide by 0, but I'm actually not familiar enough with the math to know what's going on unless I dig in further.