C# .net 抽稀算法 等距取样
数据抽稀:
一堆数据,要求尽可能均匀的从中取出数据。例如,从长度为100的数据中取出9个,索引分别是0, 11, 22, 33, 44, 56, 67, 78, 89。
/// <summary> /// 测试抽稀算法 /// </summary> /// <param name="inputLen">待抽样数据长度,自动生成</param> /// <param name="samplLen">抽稀长度</param> public List<int> DataSamplingTest(int inputLen, int samplLen) { //生成待抽稀数据 List<int> inputData = new List<int>(); for (int i = 0; i < inputLen; ) { inputData.Add(i++);//模拟索引值 } //确定取样数据 var IndexList= DataSampling(inputLen, samplLen); //取样数据 List<int> retData = new List<int>(); for (int k = 0; k < IndexList.Count; k++) { var currentIndex = IndexList[k]; var currentData = inputData[currentIndex]; retData.Add(currentData); } return retData; } /// <summary> /// 数据抽样-抽稀算法:等距(尽量)取样取前点,返回的是各取样点在原数据中的索引值的List /// </summary> /// <param name="inputLen">待处理数据引长度</param> /// <param name="samplLen">期望数据长度</param> /// <returns></returns> private List<int> DataSampling(int inputLen, int samplLen) { //生成索引列表 List<int> inputData = new List<int>(); for (int i = 0; i < inputLen;) { inputData.Add(i++); } //取样 List<int> retData = new List<int>(); // inputLen>= len double initStepSize = (double)inputLen / samplLen;//初始步长 // 兼容inputLen< len 的情况 if (initStepSize < 1) initStepSize = 1; List<int> IndexList = new List<int>();//取值索引 for (int i = 0, n = 0; i < inputLen || n < samplLen; n++)//i是待处理数据的索引,n是循环次数 { var currentInitIndex = n* initStepSize; var currentIndex = this.NearestInteger(currentInitIndex); if (currentIndex >= inputLen) { break; } if (IndexList.Contains(currentIndex)) { currentIndex++; if (currentIndex >= inputLen) break; } IndexList.Add(currentIndex); i = currentIndex; } return IndexList; } /// <summary> /// 取浮点数最接近的整数(优先向下取整) /// </summary> /// <param name="input"></param> /// <returns></returns> private int NearestInteger(double input) { int ret = 0; double inputCeiling = Math.Ceiling(input);//向上取整 double stepSizeFloor = Math.Floor(input);//向下取整 if (Math.Abs(inputCeiling - input) >= Math.Abs(input - stepSizeFloor)) { ret = (int)stepSizeFloor; } else { ret = (int)inputCeiling; } return ret; }
此处给出了一种解决方案,即 尽可能的等分数据后,取每一段数据的第一个。
还可以采用 取每段的最后一个数据的方式,或取中间位置数据的方式。
取最后一个数据,大致可修改如下:
List<int> IndexList = new List<int>();//取值索引 for (int i = 0, n = 1; i < inputLen || n <= samplLen; n++)//i是待处理数据的索引,n是循环次数 -----将n改为从1开始取值,此时可能会出现实际采样数据少于要求的取样次数的情况,做一下判断处理即可 { var currentInitIndex = n* initStepSize; var currentIndex = this.NearestInteger(currentInitIndex); if (currentIndex >= inputLen) { break; } if (IndexList.Contains(currentIndex)) { currentIndex++; if (currentIndex >= inputLen) break; } IndexList.Add(currentIndex); i = currentIndex; }
取中间位置数据雷同稍复杂一步,在于确定中间位置是谁,其核心思想与NearestInteger方法类似,此处不再赘述。
斩后知

浙公网安备 33010602011771号