Average如果函数的结果是“#VALUE!”
这是我的数据的屏幕截图。
Dim dBT As Object 'global dictionary Sub buttonpresscount() 'constants for column positions Const COL_BLOCK As Long = 1 Const COL_TRIAL As Long = 2 Const COL_ACT As Long = 7 Const COL_AOI As Long = 8 Const COL_RT As Long = 16 Const COL_FT As Long = 17 Dim rng As Range, lastrow As Long, sht As Worksheet Dim d, r As Long, k, resBT() Set sht = Worksheets("full test") lastrow = sht.Cells(Rows.Count, 3).End(xlUp).Row Set dBT = CreateObject("scripting.dictionary") Set rng = sht.Range("B7:T" & lastrow) d = rng.Value 'get the data into an array ReDim resBT(1 To UBound(d), 1 To 1) 'resize the array which will ' be placed in ColT 'get unique combinations of Block and Trial and pressedcounts for each For r = 1 To UBound(d, 1) k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = dBT(k) + IIf(d(r, COL_ACT) <> "", 1, 0) Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r 'place array to sheet sht.Range("T7").Resize(UBound(resBT, 1), 1) = resBT 'clear dictionary dBT.RemoveAll 'count AOI entries For r = 1 To UBound(d, 1) k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key If resBT(r, 1) = 1 Then 'only proceed with trials with 1 button press dBT(k) = dBT(k) + IIf(d(r, COL_AOI) = "AOI Entry", 1, 0) 'get count Else: dBT(k) = "" End If Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r 'place array to sheet sht.Range("U7").Resize(UBound(resBT, 1), 1) = resBT Call createsummarytable Call PopSummaryAOI(dBT) dBT.RemoveAll 'retrieve and print reaction times to data summary sheet For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then 'if buttonpresscount = 1 and AOI count exists k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = d(r, COL_RT) End If Next r 'Populate array with last row reaction time for each trial For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r Call PopSummaryRT(dBT) dBT.RemoveAll 'work out avg fixation time per trial For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry")) End If Next r 'populate array For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r Call PopSummaryFT(dBT) End Sub
参照上面的macros,下面的代码行是为了计算列R中每个字典(键)的平均值(读取:每个试验):
For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry")) End If Next r
这是#VALUE!
被打印在相关的单元格中,而不是预期的数量。
截图:
这是什么原因造成的? 什么是编码这个公式的正确方法?
你现在的问题与线
dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry"))
是因为你试图取平均值的唯一值,只有当这个值是True
或False
。 例如,当r
是1时,您的代码等同于
dbt("Block 1|Trial, 8") = Application.AverageIf(-2484, ("" = "AOI Entry"))
要么
dbt("Block 1|Trial, 8") = Application.AverageIf(-2484, False)
由于平均范围(即值-2484
)中的值-2484
符合标准(即False
),函数试图将匹配值的总和(即0
)除以匹配值的计数(即0
)和错误出。
同样,当r
是2时,代码等同于
dbt("Block 1|Trial, 1") = Application.AverageIf(31, ("AOI Entry" = "AOI Entry"))
要么
dbt("Block 1|Trial, 1") = Application.AverageIf(31, True)
再次, 31
不等于True
,你最终试图将0除以0。
如果你使用了一个公式,你会得到一个答案(虽然不是一个有意义的答案)
dBT(k) = Application.AverageIf(d(r, COL_AOI), "AOI Entry", d(r, COL_FT))
如果d(r, COL_AOI)
(符合标准的testing范围)符合AOI Entry"
(标准) d(r, COL_FT)
(平均范围)(总结单个数字有点没有意义,但是它仍然会这样做)。但是,当d(r, COL_AOI)
不是"AOI Entry"
时,这仍然会给出零误差的分割,并且在它工作的情况下会给出无意义的答案。
为了得到一个有意义的平均值,你需要将一个值的总和除以一个数值。 您的代码不是以易于使用Excel的内置函数来计算总和和计数的方式设置的,因此您需要计算总和并自行计算。
在下面的代码中,我添加了两个字典(一个叫Cnts
,另一个叫Cnts
)来跟踪这些数字。 然后可以通过将Cnts(k)
除以Cnts(k)
来容易地导出平均值。
我也冒昧把variablesk
数组。 你目前的代码是至less在8个位置计算密钥,所以我改变它来计算一次,然后在每个其他位置使用相同的值。
Dim dBT As Object 'global dictionary Sub buttonpresscount() Dim Sums As Object Dim Cnts As Object 'constants for column positions Const COL_BLOCK As Long = 1 Const COL_TRIAL As Long = 2 Const COL_ACT As Long = 7 Const COL_AOI As Long = 8 Const COL_RT As Long = 16 Const COL_FT As Long = 17 Dim rng As Range, lastrow As Long, sht As Worksheet Dim d, r As Long, resBT() Dim k() As String Set sht = Worksheets("full test") lastrow = sht.Cells(Rows.Count, 3).End(xlUp).Row Set dBT = CreateObject("scripting.dictionary") Set Sums = CreateObject("scripting.dictionary") Set Cnts = CreateObject("scripting.dictionary") Set rng = sht.Range("B7:T" & lastrow) d = rng.Value 'get the data into an array ReDim resBT(1 To UBound(d), 1 To 1) 'resize the array which will ' be placed in ColT ReDim k(1 To UBound(d, 1)) As String 'get unique combinations of Block and Trial and pressedcounts for each For r = 1 To UBound(d, 1) 'Calculate the key once, then it can be used in every other loop k(r) = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k(r)) = dBT(k(r)) + IIf(d(r, COL_ACT) <> "", 1, 0) Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r 'place array to sheet sht.Range("T7").Resize(UBound(resBT, 1), 1) = resBT 'clear dictionary dBT.RemoveAll 'count AOI entries For r = 1 To UBound(d, 1) If resBT(r, 1) = 1 Then 'only proceed with trials with 1 button press If d(r, COL_AOI) = "AOI Entry" Then dBT(k(r)) = dBT(k(r)) + 1 'get count Cnts(k(r)) = Cnts(k(r)) + 1 'get count Sums(k(r)) = Sums(k(r)) + d(r, COL_FT) 'sum column R End If Else dBT(k(r)) = "" End If Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r 'place array to sheet sht.Range("U7").Resize(UBound(resBT, 1), 1) = resBT createsummarytable PopSummaryAOI dBT dBT.RemoveAll 'retrieve and print reaction times to data summary sheet For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then 'if buttonpresscount = 1 and AOI count exists dBT(k(r)) = d(r, COL_RT) End If Next r 'Populate array with last row reaction time for each trial For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r PopSummaryRT dBT dBT.RemoveAll 'work out avg fixation time per trial For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then If Cnts(k(r)) < 1 Then 'Error if no results dBT(k(r)) = CVErr(xlErrDiv0) Else 'Determine average dBT(k(r)) = Sums(k(r)) / Cnts(k(r)) End If End If Next r 'populate array For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r PopSummaryFT dBT End Sub