c# - 从大型数据集中获取样本集

标签 c# linq

我有一个内存数据集,我正在尝试使用 LINQ 获取均匀分布的样本。据我所知,没有任何东西可以开箱即用,所以我正在尝试提出某种组合或扩展来执行采样。

我希望的是我可以像这样使用的东西:

var sample = dataset.Sample(100);
var smallSample = smallDataset.Sample(100);

Assert.IsTrue(dataset.Count() > 100);
Assert.IsTrue(sample.Count() == 100);

Assert.IsTrue(smallDataset.Count() < 100);
Assert.IsTrue(smallSample .Count() == smallDataset.Count());

我开始的构图,但只在某些时候有效:

var sample = dataset
             .Select((v,i) => new Tuple<string, int>(v,i))
             .Where(t => t.Item2 / (double)(dataset.Count() / SampleSize) % 1 != 0)
             .Select(t => t.Item1);

当数据集和样本大小共享一个共同的因子并且样本大小大于数据集大小的 50% 时,此方法有效。或者类似的东西。

任何帮助都会很棒!

更新:所以我有以下-LINQ 逻辑可以工作,但我想弄清楚这是否可以以某种方式“LINQ”。

var sample = new List<T>();
double sampleRatio = dataset.Count() / sampleSize;

for (var i = 0; i < dataset.Count(); i++)
{
    if ((sample.Count() * sampleRatio) <= i) 
        sample.Add(dataset.Skip(i).FirstOrDefault();
}

最佳答案

我找不到令人满意的 LINQ 解决方案,主要是因为迭代 LINQ 语句不知道它们所处理的序列的长度——这没关系:它完全适合 LINQ 的延迟执行和流式处理方法。当然,可以将长度存储在变量中并在 Where 语句中使用它,但这不符合 LINQ 的函数式(无状态)范式,因此我总是尽量避免这种情况。

Aggregate 语句可以是无状态和长度感知的,但我倾向于使用 Aggregate 找到解决方案,而不是做作且难以阅读。它只不过是一个隐蔽的状态循环; forforeach 需要更多行,但更容易理解。

我可以为您提供一个扩展方法来满足您的需求:

public static IEnumerable<T> TakeProrated<T>(this IEnumerable<T> sequence, int numberOfItems)
{
    var local = sequence.ToList();
    var n = Math.Min(local.Count, numberOfItems);
    var dist = (decimal)local.Count / n;

    for (int i = 0; i < n; i++)
    {
        var index = (int)(Math.Ceiling(i * dist));
        yield return local[index];
    }
}

想法是首先计算项目之间所需的距离。然后返回请求的元素数量,每次大致跳过这个距离,有时多,有时少,但分布均匀。使用 Math.CeilingMath.Floor 是任意的,它们要么偏向序列中较高的项目,要么偏向较低的项目。

关于c# - 从大型数据集中获取样本集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42634709/

相关文章:

c# - WPF/C# 将 ObservableCollection 中的项目的属性更改更新到 ListBox

c# - linq从属性等于值的对象数组中删除项目

.net - OrderBy、GetNewBindingList 和 Linq to SQL

c# - 如何添加自定义后应用的通用后处理

c# - 如何在 C# 中获取安装程序类中的 msi 路径

c# - 有什么方法可以在执行之后/期间延迟执行针对 IQueryable<T> 的委托(delegate)?

c# - Linq PredicateBuilder - 多个 OR

c# - 已经有一个打开的 DataReader 必须先关闭

c# - 我如何指定/调试 :embedded from csproj?

c# - 为什么将 List<Term> 的参数重构为 IEnumerable<Term>?