Arrays 如何将另一个数组的某些元素求和为一个新数组,以创建移动平均值

Arrays 如何将另一个数组的某些元素求和为一个新数组,以创建移动平均值,arrays,vba,excel,sum,elements,Arrays,Vba,Excel,Sum,Elements,我一直在工作表上使用范围引用进行计算,但现在我开始使用数组处理数据,因为数组的速度要快得多。我将要处理数十亿次的计算,所以我需要在内存中尽可能多地做。在提供的代码片段中,我试图获得“SMA_MIN_数组”,以计算名为vArray的数组的前50个值的50个周期移动平均值。有人知道如何做到这一点吗?这是我到目前为止所拥有的,我无法让它发挥作用。“总和(vArray(j,j+49)/50)是罪魁祸首。我知道这是不对的,但我需要给比我更有阵列经验的人一个想法来解释我真正想要的。我只是不知道如何将这转化为

我一直在工作表上使用范围引用进行计算,但现在我开始使用数组处理数据,因为数组的速度要快得多。我将要处理数十亿次的计算,所以我需要在内存中尽可能多地做。在提供的代码片段中,我试图获得“SMA_MIN_数组”,以计算名为vArray的数组的前50个值的50个周期移动平均值。有人知道如何做到这一点吗?这是我到目前为止所拥有的,我无法让它发挥作用。“总和(vArray(j,j+49)/50)是罪魁祸首。我知道这是不对的,但我需要给比我更有阵列经验的人一个想法来解释我真正想要的。我只是不知道如何将这转化为项目1到50之和,并将总和除以50。然后SMA_MIN_阵列的第二个元素将计算元素的平均值nts 2到51等等。有什么想法吗?下面是我尝试过的一些代码片段:(如果你住在达拉斯,我会为你买一杯你喜欢的饮料来帮助解决这个问题!)

谢谢, 尼克


下面的宏显示了如何实现我相信您所寻求的结果

我将工作表MoveAvg的单元格A1设置为
=Rand()*1000
。我将其向下拖到单元格A1500。我只对该范围的值进行了特殊粘贴,因此随机值是固定的

我将单元格C50设置为单元格A1:50的平均值。我将其向下拖动

我运行了下面的宏,它创建了一个包含移动平均数的数组。这个数组从第50行开始写入E列

下图显示Excel计算的值与宏计算的值相匹配

然而,VBA并不是用来执行“数十亿次计算”的语言

我最近回答了一个问题,涉及到计算80.63亿个值并将它们写入磁盘,每个文件有100万个值。使用VBA计算和保存5000万个值需要13分15秒。相乘意味着所有80.63亿个值的总时间将近14天20小时。使用VB.Net,计算和存储所有80.63亿个值耗时51分钟

使用VB.Net读取和写入Excel工作簿的速度比使用VBA慢。但是,一旦数据位于VB.Net数组中,计算速度就会快上千倍

VB.Net是VBA的升级版,因此学习曲线不会太陡。VB.Net的快速版本可以免费下载,如果注册,您可以分发您编写的任何程序

我让你考虑一下

Option Explicit
Sub CalcMovingAvg()

  Dim MoveAvg() As Double
  Dim RowTVLast As Long
  Dim RowTVCrnt As Long
  Dim TestValues As Variant
  Dim TotalRunning As Double

  Application.ScreenUpdating = False
  Application.EnableEvents = False
  Application.Calculate = False

  With Worksheets("MoveAvg")
    RowTVLast = .Cells(Rows.Count, 1).End(xlUp).Row
    TestValues = .Range(.Cells(1, 1), .Cells(RowTVLast, 1)).Value
  End With

  ReDim MoveAvg(1 To UBound(TestValues, 1) - 49, 1 To 1)

  TotalRunning = 0
  For RowTVCrnt = 1 To 50
    TotalRunning = TotalRunning + TestValues(RowTVCrnt, 1)
  Next

  MoveAvg(1, 1) = TotalRunning / 50

  For RowTVCrnt = 51 To UBound(TestValues, 1)
    TotalRunning = TotalRunning - TestValues(RowTVCrnt - 50, 1) + TestValues(RowTVCrnt, 1)
    MoveAvg(RowTVCrnt - 49, 1) = TotalRunning / 50
  Next

  With Worksheets("MoveAvg")
    .Range(.Cells(50, 5), .Cells(RowTVLast, 5)).Value = MoveAvg
  End With

  Application.ScreenUpdating = True
  Application.EnableEvents = True
  Application.Calculate = True

End Sub

谢谢!我开始想知道我是否必须实现SAS才能为我做到这一点。我将获得VB.Net,因为我正在工作中学习繁重的建模和理论假设。我非常感谢你的帮助,并期待着学习VB.Net!你的帮助是无价的。我希望你有一个美好的一天!Nick
Option Explicit
Sub CalcMovingAvg()

  Dim MoveAvg() As Double
  Dim RowTVLast As Long
  Dim RowTVCrnt As Long
  Dim TestValues As Variant
  Dim TotalRunning As Double

  Application.ScreenUpdating = False
  Application.EnableEvents = False
  Application.Calculate = False

  With Worksheets("MoveAvg")
    RowTVLast = .Cells(Rows.Count, 1).End(xlUp).Row
    TestValues = .Range(.Cells(1, 1), .Cells(RowTVLast, 1)).Value
  End With

  ReDim MoveAvg(1 To UBound(TestValues, 1) - 49, 1 To 1)

  TotalRunning = 0
  For RowTVCrnt = 1 To 50
    TotalRunning = TotalRunning + TestValues(RowTVCrnt, 1)
  Next

  MoveAvg(1, 1) = TotalRunning / 50

  For RowTVCrnt = 51 To UBound(TestValues, 1)
    TotalRunning = TotalRunning - TestValues(RowTVCrnt - 50, 1) + TestValues(RowTVCrnt, 1)
    MoveAvg(RowTVCrnt - 49, 1) = TotalRunning / 50
  Next

  With Worksheets("MoveAvg")
    .Range(.Cells(50, 5), .Cells(RowTVLast, 5)).Value = MoveAvg
  End With

  Application.ScreenUpdating = True
  Application.EnableEvents = True
  Application.Calculate = True

End Sub