所以基本上我正在处理一张数据表,最多约200,000行。数据的格式如下所示(伪数据)。我正在尝试分析每个周期,以确保每个周期都达到了一定的温度和压力范围(例如,对于任何给定的周期,温度都在120-130之间)。
cycle temperature pressure
1 120 321
1 121 332
1 122 323
2 123 334
2 124 326
3 125 337
3 126 328
3 127 339
3 128 320
4 129 334
我很自信能够使用一些if语句来查看是否已达到每个温度/压力,但是给我带来麻烦的那部分是能够将其分解为能够逐周期分析(例如,周期1在范围内,周期2在范围内)。如果周期长度相同,这将是相当简单的,但是它们通常通常会变化1或2个值。
我目前的想法是查看第一个循环值,然后遍历各行。如果每行的周期值等于所需值(从周期1开始),那么将评估我想要的if语句。如果到达周期2,则我们增加var,使其等于周期2。
var = ThisWorkbook.Sheets("Data").Range("A2")
For i = 2 To lastRow
If ThisWorkbook.Sheets("Data").Cells(i, 1) = var Then
'various if statements go here
Else
var = var + 1
End If
next i
现在这有很多问题,一个是每个新循环的第一个值被跳过。但是主要问题是完全忽略了“逐周期”评估的能力。
大多数人只是想获得一些帮助,以考虑如何将其按周期分为几部分。我的直觉告诉我嵌套的循环,但是我不确定如何说“这是一个新的循环,请转到下一个循环”。
答案 0 :(得分:1)
您应该能够执行以下操作(假设ColA按cycle
排序并且没有空单元格)
Dim c as range, i as long
Set c = ThisWorkbook.Sheets("Data").Range("A2")
Do While c.Value <> ""
i = application.Countif(c.parent.columns(1),c.value)
'Process i rows of data
Set c = c.offset(i, 0) '<< start of next block
Loop
答案 1 :(得分:0)
这是您可以根据需要调整的功能。它以数据范围为输入,查找值超出范围的所有周期,并返回不良周期“标题编号”的集合。可以将它们放在另一个范围内,在消息框中打印,或以其他方式处理。
Public Function findBadCycles(rngRangeToCheck As Range) As Collection
Dim dblMinTemp As Double
Dim dblMaxTemp As Double
Dim dblMinPress As Double
Dim dblMaxPress As Double
dblMinTemp = 120
dblMaxTemp = 130
dblMinPress = 320
dblMaxPress = 340
Dim colBadCycles As Collection
Set colBadCycles = New Collection
Dim i As Long
For i = 2 To rngRangeToCheck.Rows
If rngRangeToCheck.Cells(i, 2) < dblMinTemp Or rngRangeToCheck.Cells(i, 2) > dblMaxTemp Then
colBadCycles.Add rngRangeToCheck.Cells(i, 1).Value
elseif (rngRangeToCheck.Cells(i, 3) < dblMinPress) Or (rngRangeToCheck.Cells(i, 3) > dblMaxPress):
colBadCycles.Add rngRangeToCheck.Cells(i, 1).Value
End If
Next i
Set findBadCycles = colBadCycles
End Function
答案 2 :(得分:0)
对于200,000行,使用Variant Array
方法会更快
一个简单的for循环遍历数组,标识每个循环的第一行和最后一行,然后执行该循环的循环以处理数据。
像这样的东西
我提供了一个示例,说明如何处理数据:返回“温度和压力”的“最小”,“最大”,“平均”和“人口标准偏差”,该偏差位于每个“循环”的第一项旁边的行中 (由于您没有说出实际的处理方式,因此请将其作为模板并进行更新以满足您的需求)
在我的硬件上,随机数据集200,000行上的运行时间为1.7秒
Sub Demo()
Dim rngDat As Range
Dim rngRes As Range
Dim dat As Variant
Dim res As Variant
Dim FirstOfCycle As Long
Dim LastOfCycle As Long
Dim Cycle As Long
Dim i As Long, j As Long
Set rngDat = Range(Cells(2, 3), Cells(Rows.Count, 1).End(xlUp))
'Example: set return range to 4 columns next to data
Set rngRes = rngDat.Columns(rngDat.Columns.Count + 1).Resize(, 8)
dat = rngDat.Value2
rngRes.ClearContents
res = rngRes.Value2
FirstOfCycle = 1
For i = 1 To UBound(dat, 1) - 1
If dat(i + 1, 1) <> dat(i, 1) Then
LastOfCycle = i
Cycle = dat(i, 1)
ProcessCycle dat, res, FirstOfCycle, LastOfCycle
FirstOfCycle = i + 1
End If
Next
If dat(i, 1) = dat(FirstOfCycle, 1) Then
ProcessCycle dat, res, FirstOfCycle, i
Else
ProcessCycle dat, res, i, i
End If
rngRes.Value = res
End Sub
Private Sub ProcessCycle(dat As Variant, result As Variant, FirstOfCycle As Long, LastOfCycle As Long)
Dim i As Long
Dim MnT As Double, MxT As Double
Dim AvgT As Double, SdT As Double
Dim SumT As Double, SumT2 As Double
Dim MnP As Double, MxP As Double
Dim AvgP As Double, SdP As Double
Dim SumP As Double, SumP2 As Double
MnT = dat(FirstOfCycle, 2)
MxT = dat(FirstOfCycle, 2)
MnP = dat(FirstOfCycle, 3)
MxP = dat(FirstOfCycle, 3)
For i = FirstOfCycle To LastOfCycle
If dat(i, 2) < MnT Then MnT = dat(i, 2)
If dat(i, 2) > MxT Then MxT = dat(i, 2)
If dat(i, 3) < MnP Then MnP = dat(i, 3)
If dat(i, 3) > MxP Then MxP = dat(i, 3)
SumT = SumT + dat(i, 2)
SumT2 = SumT2 + dat(i, 2) ^ 2
SumP = SumP + dat(i, 3)
SumP2 = SumP2 + dat(i, 3) ^ 2
Next
result(FirstOfCycle, 1) = MnT
result(FirstOfCycle, 2) = MxT
result(FirstOfCycle, 3) = SumT / (LastOfCycle - FirstOfCycle + 1)
result(FirstOfCycle, 4) = Sqr(SumT2 / (LastOfCycle - FirstOfCycle + 1) - result(FirstOfCycle, 3) ^ 2)
result(FirstOfCycle, 5) = MnP
result(FirstOfCycle, 6) = MxP
result(FirstOfCycle, 7) = SumP / (LastOfCycle - FirstOfCycle + 1)
result(FirstOfCycle, 8) = Sqr(SumP2 / (LastOfCycle - FirstOfCycle + 1) - result(FirstOfCycle, 7) ^ 2)
End Sub