如何根据类别组内的统计数据评估一个条件?

首先,我将展示一下我的数据和我到目前为止的代码的一个简单例子,所以解释我的问题会更容易一些。

考虑以下数据:

ID Esp DBH Cod 55 E_grandis 9.00 55 E_grandis 9.71 7 55 E_grandis 10.00 55 E_grandis 1.00 7 55 E_grandis 7.00 7 55 E_grandis 1 

我试图validation如果行与Cod = 7具有大于以下值:

  average of DBH - 1 * standard deviation of DBH. 

在上面的例子中,DBH的平均值是7.34,标准偏差是3.73。 因此,标记Cod 7时,DBH值不应大于3.61(7.34 – 3.73)。

细胞D3和D6不通过标准,因为它们的DBH(C3和C6)大于3.61。 在所有具有Cod 7的行中,只有C5小于3.61。

我写下面的代码显示一个消息框,当这样的标准不符合:

 Sub Cod7() Dim msg As String 'msg box Dim ID As Range Dim dbh_stdev As Double 'standard deviation of dbh Dim dbh_avg As Double 'average of dbh Dim not_dominated As Double 'criteria threshold (upper bound) Dim cell_i As Range 'initial of array to compute average and standard deviation Dim cell_e As Range 'end of array to compute average and standard deviation msg = "" Set cell_i = Range("C2") Set cell_e = Range("C7") dbh_stdev = WorksheetFunction.StDev(Range(cell_i, cell_e)) 'dbh standard deviation dbh_avg = WorksheetFunction.Average(Range(cell_i, cell_e)) 'dbh average not_dominated = dbh_avg - dbh_stdev 'upper bound 'searches cells with cod 7 on column Cod, and it displays a message box if 'DBH is greater than the 'not_dominated' variable value For Each ID In Range("A2", Range("A2").End(xlDown)) If ID.Offset(0, 3) = 7 And _ ID.Offset(0, 2) <> 0 And _ ID.Offset(0, 2) > not_dominated Then msg = msg & "Cod 7 on " & ID.Offset(0, 3).Address() & " is incorrect" & vbLf End If Next ID If Len(msg) > 0 Then MsgBox msg End Sub 

现在的问题是,在我的真实数据中,我在Esp(specie)列下有多个类别,我需要评估标准,计算每组实体内DBH的平均值和标准偏差。
物种群集群,即一个物种通过相邻的行发生。

例如,这是在Esp列下的两个类别的最小数据:E_grandis和E_citriodora。

 ID Esp DBH Cod 55 E_grandis 9.00 55 E_grandis 9.71 7 55 E_grandis 10.00 55 E_grandis 1.00 7 55 E_grandis 7.00 7 55 E_grandis 1 55 E_citriodora 3.00 55 E_citriodora 2.00 7 55 E_citriodora 2.00 7 55 E_citriodora 1 55 E_citriodora 1 55 E_citriodora 0.50 7 

E_citriodora的平均胸径为1.88,标准偏差为1.03。 Cod = 7的行的DBH不能大于0.85(1.88-1.03)。 在这种情况下,单元C9和C10不通过标准,单元C13通过。

我如何调整代码以在“Esp”组中应用这样的标准?

我相信下面的代码是你想要的。 请注意, 只有将所有物种“分组”在一起才能起作用

我已经添加了一个外部循环,允许代码遍历所有有数据的行(具体来说,在ID中有一个值)。

起始单元( cell_i )的初始值与原始代码中的C2一样,但是我改变了它计算结束单元格( cell_e )的方式:它现在基于列B中具有与cell_i相同的值的行数(这就是CountIf正在做的事情,这就是为什么只有所有物种聚集在一起才能起作用)。

这与Set cell_i = cell_e.Offset(1)使得循环从物种的第一行跳到下一个等等。

例如,第一次对您的样本数据运行时, cell_i将是C2cell_e将是C7因为列B中具有E_grandis的行数是6,从cell_i的当前行减去1并且偏移意味着它会从当前select一个5行的单元格。

第二次从C8开始,经过C12 。 等等。

在循环体内,我已经把你的原始代码(主要是“不受伤害”)。 我刚刚调整了For循环,以便遍历范围( cell_icell_egroupRangevariables中捕获的)中的单元格,而不是在列A中具有值的所有行之间进行迭代。

我已经添加了几个Select调用,以便您可以在逐步执行代码时遵循ccellgroupRange的值。

 Option Explicit Public Sub Cod7() Dim msg As String 'msg box Dim dbh_stdev As Double 'standard deviation of dbh Dim dbh_avg As Double 'average of dbh Dim not_dominated As Double 'criteria threshold (upper bound) Dim cell_i As Range 'initial of array to compute average and standard deviation Dim cell_e As Range 'end of array to compute average and standard deviation Dim ccell As Range 'current cell Dim groupRange As Range msg = "" Set cell_i = Range("C2") Do While cell_i.Offset(, -2) <> "" Set cell_e = cell_i.Offset(WorksheetFunction.CountIf(Range("B:B"), cell_i.Offset(, -1).Value) - 1) Set groupRange = Range(cell_i, cell_e) groupRange.Select dbh_stdev = WorksheetFunction.StDev(groupRange) 'dbh standard deviation dbh_avg = WorksheetFunction.Average(groupRange) 'dbh average not_dominated = dbh_avg - dbh_stdev 'upper bound 'searches cells with cod 7 on column Cod, and it displays a message box if 'DBH is greater than the 'not_dominated' variable value For Each ccell In groupRange ccell.Select If ccell.Offset(, 1).Value = 7 And _ ccell.Value <> 0 And _ ccell.Value > not_dominated Then msg = msg & "Cod 7 on " & ccell.Offset(, 1).Address() & " is incorrect" & vbLf End If Next Set cell_i = cell_e.Offset(1) Loop If Len(msg) > 0 Then MsgBox msg End Sub 

或者你可以将整个脚本全部删除,并在单元格E2中使用此公式(然后复制,粘贴):

{=IF(AND(D2=7,C2>AVERAGEIF($B$2:$B$13,B2,$C$2:$C$13)-1* STDEV(IF($B$2:$B$13=B2,$C$2:$C$13))),"warning","")}

注意数组公式 – 记得用ctrl-shift-enter

在你的鞋子里,我会写代码来列出每个可能的ESP值。 我将每个数据点与这个列表进行比较,并保持运行总数来开发平均DBH,再次将DBH与列表进行比较以产生标准差,编制列表中每个ESP的最小/最大可接受DBH,然后制作一个最终通过检查实际DBH与最小/最大DBH的特定ESP值并应用编码程序。