예제 #1
0
        /// <summary>
        /// 混合处理,降采样和插值,不保留边界节点
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="size">桶大小。如60/3600/86400</param>
        /// <param name="offset">偏移量。时间不是对齐零点时使用</param>
        /// <returns></returns>
        public TimePoint[] Process(TimePoint[] data, Int32 size, Int32 offset = 0)
        {
            if (data == null || data.Length < 2)
            {
                return(data);
            }
            if (size <= 1)
            {
                return(data);
            }

            var xs = new Int64[data.Length];

            for (var i = 0; i < data.Length; i++)
            {
                xs[i] = data[i].Time;
            }

            var buckets = SamplingHelper.SplitByFixedSize(xs, size, offset);

            // 每个桶选择一个点作为代表
            var sampled = new TimePoint[buckets.Length];
            var last    = 0;

            for (var i = 0; i < buckets.Length; i++)
            {
                // 断层,插值
                var item = buckets[i];
                if (item.Start < 0)
                {
                    // 取last用于插值起点,如果不存在,可以取0点
                    // 此时End指向下一个有效点,即使下一个桶也是断层
                    sampled[i].Time  = i * size;
                    sampled[i].Value = Interpolation.Process(data, last, item.End, i);
                    continue;
                }

                TimePoint point = default;
                var       vs    = 0.0;
                for (var j = item.Start; j < item.End; j++)
                {
                    vs += data[j].Value;
                }
                last        = item.End - 1;
                point.Value = vs / (item.End - item.Start);

                // 对齐
                point.Time = AlignMode switch
                {
                    AlignModes.Right => (i + 1) * size - 1,
                    AlignModes.Center => data[(Int32)Math.Round((i + 0.5) * size)].Time,
                    _ => i * size,
                };
                sampled[i] = point;
            }

            return(sampled);
        }
예제 #2
0
        /// <summary>
        /// 降采样处理
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="threshold">阈值,采样数</param>
        /// <returns></returns>
        public TimePoint[] Down(TimePoint[] data, Int32 threshold)
        {
            if (data == null || data.Length < 2)
            {
                return(data);
            }
            if (threshold < 2 || threshold >= data.Length)
            {
                return(data);
            }

            var buckets = SamplingHelper.SplitByAverage(data.Length, threshold, true);

            // 每个桶选择一个点作为代表
            var sampled = new TimePoint[buckets.Length];

            for (var i = 0; i < buckets.Length; i++)
            {
                var       item      = buckets[i];
                TimePoint point     = default;
                var       min_value = Double.MaxValue;
                for (var j = item.Start; j < item.End; j++)
                {
                    if (data[j].Value < min_value)
                    {
                        min_value = data[j].Value;
                        point     = data[j];
                    }
                }

                // 对齐
                switch (AlignMode)
                {
                case AlignModes.Left:
                    point.Time = data[item.Start].Time;
                    break;

                case AlignModes.Right:
                    point.Time = data[item.End - 1].Time;
                    break;

                case AlignModes.Center:
                    point.Time = data[(Int32)Math.Round((item.Start + item.End) / 2.0)].Time;
                    break;
                }

                sampled[i++] = point;
            }

            // 第一个点和最后一个点
            if (AlignMode == AlignModes.None)
            {
                sampled[0]             = data[0];
                sampled[threshold - 1] = data[data.Length - 1];
            }

            return(sampled);
        }
예제 #3
0
        /// <summary>
        /// 降采样处理
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="threshold">阈值,采样数</param>
        /// <returns></returns>
        public TimePoint[] Down(TimePoint[] data, Int32 threshold)
        {
            if (data == null || data.Length < 2)
            {
                return(data);
            }
            if (threshold < 2 || threshold >= data.Length)
            {
                return(data);
            }

            var buckets = SamplingHelper.SplitByAverage(data.Length, threshold, true);

            // 每个桶选择一个点作为代表
            var sampled = new TimePoint[buckets.Length];

            for (var i = 0; i < buckets.Length; i++)
            {
                var       item  = buckets[i];
                TimePoint point = default;
                var       vs    = 0.0;
                for (var j = item.Start; j < item.End; j++)
                {
                    vs += data[j].Value;
                }
                point.Value = vs;

                // 对齐
                switch (AlignMode)
                {
                case AlignModes.Left:
                default:
                    point.Time = data[item.Start].Time;
                    break;

                case AlignModes.Right:
                    point.Time = data[item.End - 1].Time;
                    break;

                case AlignModes.Center:
                    point.Time = data[(Int32)Math.Round((item.Start + item.End) / 2.0)].Time;
                    break;
                }

                sampled[i] = point;
            }

            return(sampled);
        }
예제 #4
0
        /// <summary>
        /// 降采样处理
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="threshold">阈值,采样数</param>
        /// <returns></returns>
        public TimePoint[] Down(TimePoint[] data, Int32 threshold)
        {
            if (data == null || data.Length < 2)
            {
                return(data);
            }
            if (threshold < 2 || threshold >= data.Length)
            {
                return(data);
            }

            var buckets = SamplingHelper.SplitByAverage(data.Length, threshold, AlignMode == AlignModes.None);

            // 三角形选择当前同相邻三个ABC点,选择B,使得三角形有效面积最大
            var sampled = new TimePoint[buckets.Length];

            for (var i = 0; i < buckets.Length; i++)
            {
                var item = buckets[i];
                // 计算每个点的有效区域,并选取有效区域最大的点作为桶的代表点
                TimePoint point    = default;
                var       max_area = -1.0;
                for (var j = item.Start + 1; j < item.End - 1; j++)
                {
                    // 选择一个点B,计算ABC三角形面积
                    var pointA = data[j - 1];
                    var pointB = data[j];
                    var pointC = data[j + 1];
                    var area   = Math.Abs(
                        (pointA.Time - pointC.Time) * (pointB.Value - pointA.Value) -
                        (pointA.Time - pointB.Time) * (pointC.Value - pointA.Value)
                        ) / 2;
                    if (area > max_area)
                    {
                        max_area = area;
                        point    = pointB;
                    }
                }

                // 对齐
                switch (AlignMode)
                {
                case AlignModes.Left:
                    point.Time = data[item.Start].Time;
                    break;

                case AlignModes.Right:
                    point.Time = data[item.End - 1].Time;
                    break;

                case AlignModes.Center:
                    point.Time = data[(Int32)Math.Round((item.Start + item.End) / 2.0)].Time;
                    break;
                }

                sampled[i++] = point;
            }

            // 第一个点和最后一个点
            if (AlignMode == AlignModes.None)
            {
                sampled[0]             = data[0];
                sampled[threshold - 1] = data[data.Length - 1];
            }

            return(sampled);
        }
예제 #5
0
        /// <summary>
        /// 混合处理,降采样和插值
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="size">桶大小。如60/3600/86400</param>
        /// <param name="offset">偏移量。时间不是对齐零点时使用</param>
        /// <returns></returns>
        public TimePoint[] Process(TimePoint[] data, Int32 size, Int32 offset = 0)
        {
            if (data == null || data.Length < 2)
            {
                return(data);
            }
            if (size <= 1)
            {
                return(data);
            }

            var xs = new Int64[data.Length];

            for (var i = 0; i < data.Length; i++)
            {
                xs[i] = data[i].Time;
            }

            var buckets = SamplingHelper.SplitByFixedSize(xs, size, offset);

            // 每个桶选择一个点作为代表
            var sampled = new TimePoint[buckets.Length];
            var last    = 0;

            for (var i = 0; i < buckets.Length; i++)
            {
                // 断层,插值
                var b = buckets[i];
                if (b.Start < 0)
                {
                    sampled[i].Time  = i * size;
                    sampled[i].Value = Interpolation.Process(data, last, b.End, i);
                    continue;
                }

                TimePoint point = default;
                var       vs    = 0.0;
                for (var j = b.Start; j < b.End; j++)
                {
                    vs += data[j].Value;
                }
                last        = b.End - 1;
                point.Value = vs / (b.End - b.Start);

                // 对齐
                switch (AlignMode)
                {
                case AlignModes.Left:
                default:
                    point.Time = i * size;
                    break;

                case AlignModes.Right:
                    point.Time = (i + 1) * size - 1;
                    break;

                case AlignModes.Center:
                    point.Time = data[(Int32)Math.Round((i + 0.5) * size)].Time;
                    break;
                }

                sampled[i] = point;
            }

            return(sampled);
        }
예제 #6
0
        /// <summary>
        /// 降采样处理
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="threshold">阈值,采样数</param>
        /// <returns></returns>
        public TimePoint[] Down(TimePoint[] data, Int32 threshold)
        {
            if (data == null || data.Length < 2)
            {
                return(data);
            }
            if (threshold < 2 || threshold >= data.Length)
            {
                return(data);
            }

            var buckets = SamplingHelper.SplitByAverage(data.Length, threshold, AlignMode == AlignModes.None);

            // 三角形选择相邻三个桶的ABC点,A是前一个桶选择点,C是后一个桶平均点,当前桶选择B,使得三角形有效面积最大
            TimePoint pointA = default;

            if (AlignMode == AlignModes.None)
            {
                pointA = data[0];
            }
            var sampled = new TimePoint[buckets.Length];

            for (var i = 0; i < buckets.Length; i++)
            {
                var item = buckets[i];
                // 计算下一个桶的平均点作为C
                TimePoint pointC = default;
                {
                    var start = buckets[i + 1].Start;
                    var end   = buckets[i + 1].End;
                    end = end < data.Length ? end : data.Length;

                    var length = end - start;
                    for (; start < end; start++)
                    {
                        pointC.Time  += data[start].Time;
                        pointC.Value += data[start].Value;
                    }
                    if (length > 0)
                    {
                        pointC.Time  /= length;
                        pointC.Value /= length;
                    }
                    else
                    {
                        pointC = data[end - 1];
                    }
                }

                // 计算每个点的有效区域,并选取有效区域最大的点作为桶的代表点
                TimePoint point = default;
                {
                    var max_area = -1.0;
                    for (var j = item.Start; j < item.End; j++)
                    {
                        // 选择一个点B,计算ABC三角形面积
                        var pointB = data[j];
                        var area   = Math.Abs(
                            (pointA.Time - pointC.Time) * (pointB.Value - pointA.Value) -
                            (pointA.Time - pointB.Time) * (pointC.Value - pointA.Value)
                            ) / 2;
                        if (area > max_area)
                        {
                            max_area = area;
                            point    = pointB;
                        }
                    }
                }
                pointA = point;

                // 对齐
                switch (AlignMode)
                {
                case AlignModes.Left:
                    point.Time = data[item.Start].Time;
                    break;

                case AlignModes.Right:
                    point.Time = data[item.End - 1].Time;
                    break;

                case AlignModes.Center:
                    point.Time = data[(Int32)Math.Round((item.Start + item.End) / 2.0)].Time;
                    break;
                }

                sampled[i++] = point;
            }

            // 第一个点和最后一个点
            if (AlignMode == AlignModes.None)
            {
                sampled[0]             = data[0];
                sampled[threshold - 1] = data[data.Length - 1];
            }

            return(sampled);
        }