c# - calculate average function of several functions -


i have several ordered list of x/y pairs , want calculate ordered list of x/y pairs representing average of these lists.

all these lists (including "average list") drawn onto chart (see example picture below).

i have several problems:

  1. the different lists don't have same amount of values
  2. the x , y values can increase , decrease , increase (and on) (see example picture below)

i need implement in c#, altought guess that's not important algorithm itself.

example of lines

sorry, can't explain problem in more formal or mathematical way.

edit: replaced term "function" "list of x/y pairs" less confusing.

i use method justin proposes, 1 adjustment. suggests using mappingtable fractional indices, though suggest integer indices. might sound little mathematical, it's no shame have read following twice(i'd have too). suppose point @ index in list of pairs has searched closest points in list b, , closest point @ index j. find closest point in b a[i+1] should consider points in b index equal or larger j. j + 1, j or j + 2, j + 3 etc, never below j. if point closest a[i+1] has index smaller j, still shouldn't use point interpolate with, since result in unexpected average , graph. i'll take moment create sample code you. hope see optimalization makes sense.

edit: while implementing this, realised j not bounded below(by method described above), bounded above. when try distance a[i+1] b[j], b[j+1], b[j+2] etc, can stop comparing when distance a[i+1] b[j+...] stops decreasing. there's no point in searching further in b. same reasoning applies when j bounded below: if point elsewhere in b closer, that's not point want interpolate with. doing result in unexpected graph, less smooth you'd expect. , bonus of second bound improved performance. i've created following code:

ienumerable<tuple<double, double>> average(list<tuple<double, double>> a, list<tuple<double, double>> b) {     if (a == null || b == null || a.any(p => p == null) || b.any(p => p == null)) throw new argumentexception();     func<double, double> square = d => d * d;//squares argument     func<int, int, double> euclidiandistance = (a, b) => math.sqrt(square(a[a].item1 - b[b].item1) + square(a[a].item2 - b[b].item2));//computes distance a[first argument] b[second argument]      int previousindexinb = 0;     (int = 0; < a.count; i++)     {         double distance = euclidiandistance(i, previousindexinb);//distance between a[i] , b[j - 1],          (int j = previousindexinb + 1; j < b.count; j++)         {             var distance2 = euclidiandistance(i, j);//distance between a[i] , b[j]             if (distance2 < distance)//if it's closer checked point, keep searching. otherwise stop search , return interpolated point.             {                 distance = distance2;                 previousindexinb = j;             }             else             {                 break;//don't place yield return statement here, because go wrong @ end of b.             }         }         yield return linearinterpolation(a[i], b[previousindexinb]);     } } tuple<double, double> linearinterpolation(tuple<double, double> a, tuple<double, double> b) {     return new tuple<double, double>((a.item1 + b.item1) / 2, (a.item2 + b.item2) / 2); } 

for information, function average returns same amount of interpolated points list contains, fine, should think specific application. i've added comments in clarify details, , i've described aspects of code in text above. hope it's clear, , otherwise feel free ask questions.

second edit: misread , thought had 2 lists of points. have created generalised function of above accepting multiple lists. still uses principles explained above.

ienumerable<tuple<double, double>> average(list<list<tuple<double, double>>> data) {     if (data == null || data.count < 2 || data.any(list => list == null || list.any(p => p == null))) throw new argumentexception();     func<double, double> square = d => d * d;     func<tuple<double, double>, tuple<double, double>, double> euclidiandistance = (a, b) => math.sqrt(square(a.item1 - b.item1) + square(a.item2 - b.item2));      var firstlist = data[0];     (int = 0; < firstlist.count; i++)     {         int[] previousindices = new int[data.count];//the indices of points closest previous point firstlist[i - 1].          //(or 0 if == 0). kept track of per list, except first list.         var closests = new tuple<double, double>[data.count];//an array of points used caching, of average yielded.         closests[0] = firstlist[i];         (int listindex = 1; listindex < data.count; listindex++)         {             var list = data[listindex];             double distance = euclidiandistance(firstlist[i], list[previousindices[listindex]]);             (int j = previousindices[listindex] + 1; j < list.count; j++)             {                 var distance2 = euclidiandistance(firstlist[i], list[j]);                 if (distance2 < distance)//if it's closer checked point, keep searching. otherwise stop search , return interpolated point.                 {                     distance = distance2;                     previousindices[listindex] = j;                 }                 else                 {                     break;                 }             }             closests[listindex] = list[previousindices[listindex]];         }         yield return new tuple<double, double>(closests.select(p => p.item1).average(), closests.select(p => p.item2).average());     } } 

actually did specific case 2 lists separately might have been thing: explained , offers step before understanding generalised version. furthermore, square root taken out, since doesn't change order of distances when sorted, lengths.

third edit: in comments became clear there might bug. think there none, aside mentioned small bug, shouldn't make difference except @ end of graphs. proof works, result of it(the dotted line average): enter image description here


Comments

Popular posts from this blog

apache - Add omitted ? to URLs -

redirect - bbPress Forum - rewrite to wwww.mysite prohibits login -

php - How can I stop spam on my custom forum/blog? -