根据第二个列表 C# 的标准差合并第一个列表和第二个列表

Merge first list with second list based on standard deviation of second list C#

给定 2 个数据集(它们都是偏离数字的标准差序列,我们正在寻找重叠部分):

var list1 = new decimal[] { 357.06, 366.88, 376.70, 386.52, 406.15 };
var list2 = new decimal[] { 370.51, 375.62, 380.72, 385.82, 390.93 };

我想对 List2 中的项目执行合并,这些项目在一定范围内最接近 List1 的项目,即合并 List2 中的元素 5.10 List1 元素的(标准偏差):

357.06
366.88 => 370.51
376.70 => 375.52, 380.72
386.52 => 390.93
406.15

想法是对 List2 中的值进行聚类并对其进行计数,在这种情况下,具有值 376.70 的元素将具有最高重要性,因为它有 2 个近邻 375.52380.72(其中 366.88386.52 只有 1 个匹配项,其余 none 在范围内)。

哪些 C# math/stats 库可用于此(或者是否有更好的统计组合方式)?

如果这更多是计算机科学或统计问题,提前致歉将在相关 SO 站点上关闭并重新打开。

像这样的东西应该可以工作

    var list1 = new double[] { 357.06, 366.88, 376.70, 386.52, 406.15 };
    var list2 = new double[] { 370.51, 375.62, 380.72, 385.82, 390.93 };

    double dev = 5.1;

    var result = new Dictionary<double, List<double>>();
    foreach (var l in  list2) {
        var diffs = list1.Select(r => new { diff = Math.Abs(r - l), r })
            .Where(d => d.diff <= dev)
            .MinBy(r => r.diff)
            .FirstOrDefault();
        if (diffs == null) {
            continue;
        }
        List<double> list;
        if (! result.TryGetValue(diffs.r, out list)) {
            list =  new List<double>();
            result.Add(diffs.r, list);
        }
        list.Add(l);
    }

它使用 MoreLinq 中的 MinBy,但没有它也很容易修改。

事实上,您不需要额外的库或其他东西。为此,您可以只使用 LINQ。

internal class Program
    {
        private static void Main(string[] args)
        {
            var deviation = 5.1M;
            var list1 = new decimal[] { 357.06M, 366.88M, 376.70M, 386.52M, 406.15M };
            var list2 = new decimal[] { 370.51M, 375.62M, 380.72M, 385.82M, 390.93M };

            var result = GetDistribution(list1.ToList(), list2.ToList(), deviation);

            result.ForEach(x => Console.WriteLine($"{x.BaseValue} => {string.Join(", ", x.Destribution)}  [{x.Weight}]"));

            Console.ReadLine();
        }

        private static List<Distribution> GetDistribution(List<decimal> baseList, List<decimal> distrebutedList, decimal deviation)
        {
            return baseList.Select(x =>
            new Distribution
            {
                BaseValue = x,
                Destribution = distrebutedList.Where(y => x - deviation < y && y < x + deviation).ToList()
            }).ToList();
        }
    }

    internal class Distribution
    {
        public decimal BaseValue { get; set; }
        public List<decimal> Destribution { get; set; }
        public int Weight => Destribution.Count;
    }

希望对你有用。

假设 list2 排序的 (如果不是,输入 Array.Sort(list2);)你可以尝试 Binary Search :

给定:

  var list1 = new decimal[] { 357.06m, 366.88m, 376.70m, 386.52m, 406.15m };
  var list2 = new decimal[] { 370.51m, 375.62m, 380.72m, 385.82m, 390.93m };

  decimal sd = 5.10m;

代码:

  // Array.Sort(list2); // Uncomment, if list2 is not sorted

  List<(decimal value, decimal[] list)> result = new List<(decimal value, decimal[] list)>();

  foreach (decimal value in list1) {
    int leftIndex = Array.BinarySearch<decimal>(list2, value - sd);

    if (leftIndex < 0)
      leftIndex = -leftIndex - 1;
    else // edge case  
      for (; leftIndex >= 1 && list1[leftIndex - 1] == value - sd; --leftIndex) ;
        
    int rightIndex = Array.BinarySearch<decimal>(list2, value + sd);

    if (rightIndex < 0)
      rightIndex = -rightIndex - 1;
    else // edge case
      for (; rightIndex < list1.Length - 1 && list1[rightIndex + 1] == value + sd; ++rightIndex) ;

    result.Add((value, list2.Skip(leftIndex).Take(rightIndex - leftIndex).ToArray()));
  }

一起来看看:

  string report = string.Join(Environment.NewLine, result
    .Select(item => $"{item.value} => [{string.Join(", ", item.list)}]"));

  Console.Write(report);

结果:

357.06 => []
366.88 => [370.51]
376.70 => [375.62, 380.72]
386.52 => [385.82, 390.93]
406.15 => []