【问题标题】:Find average of a specific number of rows/columns in VB.Net Datatable and store to array在 VB.Net 数据表中查找特定数量的行/列的平均值并存储到数组
【发布时间】:2012-06-21 07:37:40
【问题描述】:

在得到my other question 的帮助后,我正在尝试编写一种降噪算法,该算法适用于 VB.NET 数据表中的一组数据点。基本上,我想取两个整数,一个坐标值(例如yCoord)和一个阈值平滑值(NoiseThresh),然后取(yCoord - NoiseThresh, yCoord + NoiseThresh) 范围内的值的平均值并将该数字存储到大批。我会为每一列(在这个例子中)重复这个过程,最终得到一个一维的平均值数组。我的问题是:

1) 我刚才所说的一切是否有意义;),以及
2)谁能帮我写代码?我几乎没有使用数据库的经验。

谢谢!

我正在尝试做的一个例子:

//My data (pretend it's a database)
1  4  4  9  2  //yCoord would equal 5
6  3  8  12 3  //yCoord = 4
8  3 -2  2  0  //yCoord = 3
9 17  3  7  5  //yCoord = 2
4  1  0  9  7  //yCoord = 1

//In this example, my yCoord will equal 3 and NoiseThresh = 1

//For the first column
    Array(column1) = //average of the set of numbers centered at yCoord = 3 _
//(in this case 8) and the NoiseThresh=1 number on either side (here 6 & 9)
//For the second column
    Array(column2) = //average of the numbers 3,3,17 for example
    //etc., etc.,

这将在大型数据集上执行(典型数字为 yCoord=500,NoiseThresh = 50,数组长度 = 1092),因此不可能手动输入数字。

我希望这有助于澄清我的问题!

P.S.:是的,我知道 // 不是 VB.NET 注释。

【问题讨论】:

  • 这个问题的目标是内存中的DataTable,所以你说你对数据库只有很少的经验是没有意义的,不是吗?
  • 不是真的...我想说的是,我希望发布的任何代码都带有解释或 cmets。
  • 我想说的是,在数据库中完成这一切可能是一种更好的方法,如果这是一个具有多个用户的 Web 应用程序则更是如此。您正在将所有不可扩展的内容加载到内存中。使用 DataTable 的答案并不能帮助您理解 SQL。
  • 范围部分还不清楚。 xCord/yCord/NoiseThreas 指的是什么数据表? xCord 是列索引,yCord 是行位置,NoiseThreas 是范围吗?
  • xCoord/yCoord 分别指的是作为降噪算法中心点的列/行。 NoiseThresh 是要求平均值的 xCoord 左右的数据点数,或者是要求平均值的 yCoord 上下的数据点数。我想对 xCoord 指定的列中的每个数据点以及 yCoord 指定的行中的数据点重复此平均函数。

标签: database vb.net algorithm math noise-reduction


【解决方案1】:

我必须承认我还没有理解范围部分(NoiseThresh 等),但这是一个开始:

Dim averages = (From col In tbl.Columns.Cast(Of DataColumn)()
               Select tbl.AsEnumerable().
                      Average(Function(r) r.Field(Of Int32)(col.ColumnName))).
               ToArray()

它计算DataTable 中每一列的每个平均值,并根据结果创建一个Double()(即使用于整数,平均值也可能导致小数位)。

编辑:通过您的示例,我现在已经理解了范围部分。所以基本上yCord 是行索引(+1),noiseThreas 是行范围(+/- n 行)。

那么这会给你正确的结果(做了一些代码cmets):

Dim yCord = 2 ' the row index(-1 since indices are 0-based) '
Dim noiseThresh = 1 ' +/- row '
' reverse all rows since your sample begins with index=5 and ends with index=1 '
Dim AVGs As Double() = (
    From colIndex In Enumerable.Range(0, tbl.Columns.Count)
    Select tbl.AsEnumerable().Reverse().
    Where(Function(r, index) index >= yCord - noiseThresh _
                     AndAlso index <= yCord + noiseThresh).
    Average(Function(r) r.Field(Of Int32)(colIndex))).ToArray()

这个LINQ 查询中最重要的部分是Where。它将您的范围应用于IEnumerable(of DataRow)。然后我正在计算每一列的这些行的平均值。最后一步是将查询具体化为Double()

结果:

    (0) 7.666666666666667   Double  => (6+8+9)/3
    (1) 7.666666666666667   Double  => (3+3+17)/3
    (2) 3.0                 Double  => (8-2+3)/3
    (3) 7.0                 Double  => (12+2+7)/3
    (4) 2.6666666666666665  Double  => (3+0+5)/3

编辑2

最后一件事。我假设对另一个轴做同样的事情,我只是 切换 x & y 和行 & 列?

事情没那么简单。但是你自己看看:

Dim noiseThresh = 1 ' +/- column '
Dim xCord = 2 ' the column index(-1 since indices are 0-based) '
' assuming that your x-cords now start with index=0 and ends with tbl.Column.Count-1 '
Dim AVGs As Double() = (
    From rowIndex In Enumerable.Range(0, tbl.Rows.Count)
    Select tbl.Columns.Cast(Of DataColumn)().
    Where(Function(c, colIndex) colIndex >= xCord - noiseThresh _
                        AndAlso colIndex <= xCord + noiseThresh).
    Average(Function(c) tbl.Rows(rowIndex).Field(Of Int32)(c.Ordinal))).ToArray()

结果:

    (0) 5.666666666666667   Double  => (4+4+9)/3
    (1) 7.666666666666667   Double  => (3+8+12)/3
    (2) 1.0                 Double  => (3-2+2)/3
    (3) 9.0                 Double  => (17+3+7)/3
    (4) 3.3333333333333335  Double  => (1+0+9)/3

【讨论】:

  • 您能否详细说明一下在我的情况下我将如何设置它?
  • @Matt:我已经编辑了我的答案,如果您有问题,请提出。还添加了结果和计算。
  • 谢谢,这很有帮助。现在我需要为我想要获得的每个平均值循环这个吗?在我的示例中,这只是第一列,还是每列的平均值数组?
  • 最后一件事。我假设要对另一个轴做同样的事情,我只需切换 x & y 和 row & column?
  • @Matt:再次编辑以提供 x 轴版本。
猜你喜欢
  • 1970-01-01
  • 2017-06-11
  • 1970-01-01
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
  • 2021-12-22
  • 2020-09-06
相关资源
最近更新 更多