我有一个包含超过50k行的数据集。我决定取前五十个值的平均值,然后是第二个五十个值,依此类推(这样我就可以获得平均50个值组的数据集的一半)。
这是我的代码:
var Rate = (from dr in ds.Tables[0].AsEnumerable()
select new
{
rate = dr.Field<double>(columnName)
}.rate).ToList();
if (Rate.Count > 50)
{
var avg = Rate.CheckRateValue();
}
以下是我的扩展方法的代码:
public static IEnumerable<double> CheckRateValue(this IEnumerable<double> values)
{
int i = 1;
int j = 0;
for (; i < values.Count(); )
{
yield return values.Skip(j * 2).Take(2).Average();
i = i + 2;
j++;
}
}
问题: 它工作正常,但速度很慢。有没有人对如何加快它有任何建议?
答案 0 :(得分:2)
使用DataTable.Compute可能会更快,因为您跳过迭代来创建List<dobule>
。
double average = (double)ds.Tables[0].Compute("avg(columnName)", "");
第二个参数是fitler表达式,因此如果表中的数据允许,您可以使用它来跳过它。
答案 1 :(得分:1)
var yourList=yourList.Take(50).Aggregate((acc, cur) => acc + cur) / list.Count
答案 2 :(得分:1)
如果你想以五十分的数量取物品并取平均值(比如前50,平均,接下来50,平均等),并获得平均值列表,你可以使用{{3} }。MoreLinq
您可以使用
var result = list.Batch(50).Select(x=> x.Average());
答案 3 :(得分:0)
为什么这会比简单更快:
var average = dat.AsEnumerable().Average(dr => (double)dr["ColumnName"]);
事实上 - 这应该比一次服用50的额外复杂性更快......
答案 4 :(得分:0)
有 { yield return values.Skip(j * 2).Take(2).Average(); }
在每次循环迭代中从头开始移动到当前页面:这将是n ^ 2。另请参阅Schlemiel the painter。
您应该枚举values
一次!
答案 5 :(得分:0)
通过使用row_number()我解决了它。
declare @Skip int = 20
declare @Take int = 10
select SomeColumn
from (
select SomeColumn,
row_number() over(order by SomeColumnToOrderBy) as rn
from YourTable
) T
where rn > @Skip and
rn <= @Skip + @Take