/// <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); }
/// <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); }