//Interquartile Range is used in statistic to measure variability of trends private double interquartileRange(SegmentType segment, double[] timeData, double a) { double iqr = 0, distance = 0; double[] rangeData = new double[segment.rx - segment.lx + 1]; int j = 0, q1, q2; //We take all absolute distance between real data and approximated trends to array for (int i = segment.lx; i <= segment.rx; i++) { distance = Math.Abs(timeData[i] - (a * i - a * segment.lx + segment.ly)); rangeData[j] = distance; j++; } //We sort this array and then find position of 0.25 element and 0.75 element Array.Sort(rangeData); q1 = (int)(0.25 * (rangeData.Length + 1)); q2 = (int)(0.75 * (rangeData.Length + 1)); if (q1 > 0) { q1--; } if (q2 > 0) { q2--; } //element from 0.75 position - element from 0.25 position and we get Interquartile Range iqr = rangeData[q2] - rangeData[q1]; return iqr; }
public void testDeleteSegmentElement() { SegmentType[] timeSeriesData = new SegmentType[3]; timeSeriesData[0] = new SegmentType(1, 2, 3.4, 7.4, 2.4); timeSeriesData[1] = new SegmentType(3, 4, 2.4, 2.4, 2.4); timeSeriesData[2] = new SegmentType(5, 6, 9.4, 7.4, 2.4); int elementPosition = 2; TimeSeriesTrends_Accessor instance = new TimeSeriesTrends_Accessor(); SegmentType[] expResult = new SegmentType[2]; expResult[0] = new SegmentType(1, 2, 3.4, 7.4, 2.4); expResult[1] = new SegmentType(3, 4, 2.4, 2.4, 2.4); SegmentType[] result = instance.deleteSegmentElement(timeSeriesData, elementPosition); Assert.AreEqual(expResult, result); }
public double absoluteError(SegmentType[] segments, double[] timeData) { double distanceMeasure = 0, distance = 0; double a = 0; foreach (SegmentType segment in segments) { a = (segment.ry - segment.ly) / (segment.rx - segment.lx); for (int i = segment.lx; i <= segment.rx; i++) { distance = timeData[i] - (a * i - a * segment.lx + segment.ly); distanceMeasure += Math.Abs(distance) / segments.Length; } } return distanceMeasure; }
public TrendDataType[] evaluateTrendsCharacteristics(SegmentType[] timeSeriesTrends, double[] timeData) { TrendDataType[] trendData = new TrendDataType[timeSeriesTrends.Length]; for (int i = 0; i < timeSeriesTrends.Length; i++) { trendData[i] = new TrendDataType(); //Dynamics Of Change - it is trend-function angle -> a = y2 - y1 / x2 - x1 trendData[i].dynamicsOfChange = (timeSeriesTrends[i].ry - timeSeriesTrends[i].ly) / (timeSeriesTrends[i].rx - timeSeriesTrends[i].lx); //Duration - how many points trend lasts -> rx(trend end) - lx(trend start) trendData[i].duration = (double)(timeSeriesTrends[i].rx - timeSeriesTrends[i].lx + 1) / timeData.Length; //Variability - it is measured by interquartile range -> 0.75data - 0.25data trendData[i].variability = interquartileRange(timeSeriesTrends[i], timeData, trendData[i].dynamicsOfChange); } return trendData; }
private void orginalDataTrendsEquals(SegmentType[] expResult, SegmentType[] actualResult, double acceptableErrorY, int acceptableErrorX) { Assert.AreEqual(expResult.Length, actualResult.Length); for (int i = 0; i < actualResult.Length; i++) { Assert.AreEqual(expResult[i].lx, actualResult[i].lx, acceptableErrorX); Assert.AreEqual(expResult[i].rx, actualResult[i].rx, acceptableErrorX); Assert.AreEqual(expResult[i].ly, actualResult[i].ly, acceptableErrorY); Assert.AreEqual(expResult[i].ry, actualResult[i].ry, acceptableErrorY); } }
public void testMakeTrendsAlghoritm() { double[] data = new double[3793]; int segmentsNumber; SegmentType[] actualResult; TimeSeriesTrends instance = new TimeSeriesTrends(); using (System.IO.StreamReader sr = new System.IO.StreamReader("TimeSeriesData.dat")) { System.Globalization.NumberFormatInfo provider = new System.Globalization.NumberFormatInfo( ); provider.NumberDecimalSeparator = "."; string dataLine; int i = 0; while ((dataLine = sr.ReadLine()) != null) { data[i++] = Convert.ToDouble(dataLine, provider); } } segmentsNumber = 20; actualResult = instance.makeTrendsAlghoritm(data, segmentsNumber); SegmentType[] expResult = new SegmentType[20]; for (int i = 0; i < 20; i++) { expResult[i] = new SegmentType(); } expResult[0].lx = 1; expResult[1].lx = 211; expResult[2].lx = 429; expResult[3].lx = 675; expResult[4].lx = 851; expResult[5].lx = 939; expResult[6].lx = 1101; expResult[7].lx = 1363; expResult[8].lx = 1441; expResult[9].lx = 1825; expResult[10].lx = 1893; expResult[11].lx = 2223; expResult[12].lx = 2481; expResult[13].lx = 2739; expResult[14].lx = 2987; expResult[15].lx = 3013; expResult[16].lx = 3289; expResult[17].lx = 3407; expResult[18].lx = 3589; expResult[19].lx = 3681; expResult[0].rx = 210; expResult[1].rx = 428; expResult[2].rx = 674; expResult[3].rx = 850; expResult[4].rx = 938; expResult[5].rx = 1100; expResult[6].rx = 1362; expResult[7].rx = 1440; expResult[8].rx = 1824; expResult[9].rx = 1892; expResult[10].rx = 2222; expResult[11].rx = 2480; expResult[12].rx = 2738; expResult[13].rx = 2986; expResult[14].rx = 3012; expResult[15].rx = 3288; expResult[16].rx = 3406; expResult[17].rx = 3588; expResult[18].rx = 3680; expResult[19].rx = 3793; expResult[0].ly = 1137.9; expResult[1].ly = 759.6; expResult[2].ly = 1194.6; expResult[3].ly = 1652.8; expResult[4].ly = 1363.9; expResult[5].ly = 1987.8; expResult[6].ly = 1234.6; expResult[7].ly = 1444.1; expResult[8].ly = 2224.2; expResult[9].ly = 1082.3; expResult[10].ly = 1371.5; expResult[11].ly = 1210.7; expResult[12].ly = 1642.3; expResult[13].ly = 1909.4; expResult[14].ly = 3197.0; expResult[15].ly = 2824.5; expResult[16].ly = 3692.4; expResult[17].ly = 3101.6; expResult[18].ly = 1945.2; expResult[19].ly = 1436.9; expResult[0].ry = 551.6; expResult[1].ry = 946.5; expResult[2].ry = 1594.6; expResult[3].ry = 1650.4; expResult[4].ry = 1682.7; expResult[5].ry = 1119.6; expResult[6].ry = 1601.1; expResult[7].ry = 2410.1; expResult[8].ry = 1097.1; expResult[9].ry = 1302.4; expResult[10].ry = 1054.8; expResult[11].ry = 1849.3; expResult[12].ry = 2010.5; expResult[13].ry = 3116.6; expResult[14].ry = 2581.5; expResult[15].ry = 3788.0; expResult[16].ry = 3543.1; expResult[17].ry = 2455.1; expResult[18].ry = 1547.9; expResult[19].ry = 2063.5; orginalDataTrendsEquals(expResult, actualResult, 1.1, 3); }
public SegmentType[] makeTrendsAlghoritm(double[] data, int segmentsNumber) { int numberOfSegments = data.Length / 2; SegmentType[] segment = new SegmentType[numberOfSegments]; double[] coef; double[] best; //Create initial fine approximation for (int i = 0; i < numberOfSegments; i++) { segment[i] = new SegmentType(); segment[i].lx = 2 * i; segment[i].rx = 2 * i + 1; segment[i].mc = Double.PositiveInfinity; } segment[numberOfSegments - 1].rx = data.Length - 1; //find the cost of merging each pair of segments. for (int i = 0; i < numberOfSegments - 1; i++) { coef = linearApproxym(generateArray(segment[i].lx, segment[i + 1].rx), subArray(data, segment[i].lx, segment[i + 1].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i + 1].rx)); segment[i].mc = calculateError(subArray(data, segment[i].lx, segment[i + 1].rx), best); } while (segment.Length > segmentsNumber) { int i = 0; i = minError(segment); if (i > 0 && i < segment.Length - 2) { coef = linearApproxym(generateArray(segment[i].lx, segment[i + 2].rx), subArray(data, segment[i].lx, segment[i + 2].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i + 2].rx)); segment[i].mc = calculateError(subArray(data, segment[i].lx, segment[i + 2].rx), best); segment[i].rx = segment[i + 1].rx; segment = deleteSegmentElement(segment, i + 1); i--; coef = linearApproxym(generateArray(segment[i].lx, segment[i + 1].rx), subArray(data, segment[i].lx, segment[i + 1].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i + 1].rx)); segment[i].mc = calculateError(subArray(data, segment[i].lx, segment[i + 1].rx), best); } else if (i == 0) { coef = linearApproxym(generateArray(segment[i].lx, segment[i + 2].rx), subArray(data, segment[i].lx, segment[i + 2].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i + 2].rx)); segment[i].mc = calculateError(subArray(data, segment[i].lx, segment[i + 2].rx), best); segment[i].rx = segment[i + 1].rx; segment = deleteSegmentElement(segment, i + 1); } else { segment[i].rx = segment[i + 1].rx; segment[i].mc = Double.PositiveInfinity; segment = deleteSegmentElement(segment, i + 1); i--; coef = linearApproxym(generateArray(segment[i].lx, segment[i + 1].rx), subArray(data, segment[i].lx, segment[i + 1].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i + 1].rx)); segment[i].mc = calculateError(subArray(data, segment[i].lx, segment[i + 1].rx), best); } } double[] residuals = new double[segment.Length]; for (int i = 0; i < segment.Length; i++) { coef = linearApproxym(generateArray(segment[i].lx, segment[i].rx), subArray(data, segment[i].lx, segment[i].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i].rx)); residuals[i] = calculateError(subArray(data, segment[i].lx, segment[i].rx), best); } for (int i = 0; i < segment.Length; i++) { coef = linearApproxym(generateArray(segment[i].lx, segment[i].rx), subArray(data, segment[i].lx, segment[i].rx)); best = linearFunctionValues(coef[0], coef[1], generateArray(segment[i].lx, segment[i].rx)); segment[i].ly = best[0]; segment[i].ry = best[generateArray(segment[i].lx, segment[i].rx).Length - 1]; } return segment; }
private int minError(SegmentType[] timeSeriesData) { int positionI = 0; double minMc = timeSeriesData[0].mc; for (int i = 1; i < timeSeriesData.Length; i++) { if (minMc > timeSeriesData[i].mc) { minMc = timeSeriesData[i].mc; positionI = i; } } return positionI; }
private SegmentType[] deleteSegmentElement(SegmentType[] timeSeriesData, int elementPosition) { SegmentType[] remainSegment = new SegmentType[timeSeriesData.Length - 1]; int i = 0, j = 0; while (i < timeSeriesData.Length && j < remainSegment.Length) { if (i == elementPosition) { i++; } else { remainSegment[j] = timeSeriesData[i]; i++; j++; } } return remainSegment; }