Excel 如何将LinEst函数应用于行?
多年来,我一直在使用WorksheetFunction.LinEst进行二次回归,没有遇到任何问题。我的数据始终存储在Excel工作表的列中 现在我收到的数据是行,而不是列。我对WorksheetFunction.LinEst的调用失败。Excel 如何将LinEst函数应用于行?,excel,vba,Excel,Vba,多年来,我一直在使用WorksheetFunction.LinEst进行二次回归,没有遇到任何问题。我的数据始终存储在Excel工作表的列中 现在我收到的数据是行,而不是列。我对WorksheetFunction.LinEst的调用失败。 如果我在工作表中处理与公式相同的命令,则该命令有效 我没有转换数据的选项。我使用的是最新版本的Windows 10和Microsoft Office 365 我在这里找不到任何用VBA编写的、数据存储成行的示例 这是我调用以执行回归的子程序的干净副本。我已删除
如果我在工作表中处理与公式相同的命令,则该命令有效 我没有转换数据的选项。我使用的是最新版本的Windows 10和Microsoft Office 365 我在这里找不到任何用VBA编写的、数据存储成行的示例 这是我调用以执行回归的子程序的干净副本。我已删除了所有调试代码,以使其更具可读性。
完整版本在较低的位置。
下面的代码是我为演示失败而编写的一些代码
Sub GetPolynomialRegressionCoefficients(Xs As Excel.Range, Ys As Excel.Range, ByRef x1 As Double, ByRef x2 As Double, ByRef x3 As Double)
'
' Calculates the best fit cooeficients of the the data stored in ranges Xs and Ys
'
Dim rgCoeff ' This will be a variant array of the coefficients calculated for the best fit quadratic curve
rgCoeff = Application.WorksheetFunction.LinEst(Ys, Application.Power(Xs, Array(1, 2)))
x1 = rgCoeff(1)
x2 = rgCoeff(2)
x3 = rgCoeff(3)
End Sub
下面的代码创建一个简单的数据集来计算y=x^2函数的系数。使用相同的数据(先存储在列中,然后存储在行中),我的代码处理列中的数据,但处理行中的数据失败
Sub TestGetPolynomialRegressionCoefficients()
Dim rXs As Excel.Range ' Range for the X values
Dim rYs As Excel.Range ' Range for the Y values
Dim ws As Excel.Worksheet
Dim iRow As Long
Dim iCol As Long
Dim x As Long
Dim x1 As Double
Dim x2 As Double
Dim x3 As Double
Set ws = ThisWorkbook.Worksheets("LinEstTest")
'
' Works! - Test data y = x^2 with data in columns
'
ws.Cells.Clear
For x = 0 To 9
iRow = x + 1
ws.Cells(iRow, 1) = x ' these will be the domain (the Xs)
ws.Cells(iRow, 2) = x * x ' these will be the range (the Ys)
Next x
Set rXs = ws.Range(ws.Cells(1, 1), ws.Cells(10, 1))
Set rYs = ws.Range(ws.Cells(1, 2), ws.Cells(10, 2))
On Error Resume Next
x1 = -1: x2 = -1: x3 = -1
GetPolynomialRegressionCoefficients rXs, rYs, x1, x2, x3
If Err <> 0 Then
Debug.Print "Error using Columns "; Err; " "; Err.Description
Else
Debug.Print "With data in columns, x1 = "; x1; ", x2 = "; x2; ", x3 = "; x3
End If
'
' Fails! - Test data y = x^2 with data in rows
'
ws.Cells.Clear
For x = 0 To 9
iCol = x + 1
ws.Cells(1, iCol) = x ' these will be the domain (the Xs)
ws.Cells(2, iCol) = x * x ' these will be the range (the Ys)
Next x
Set rXs = ws.Range(ws.Cells(1, 1), ws.Cells(1, 10))
Set rYs = ws.Range(ws.Cells(2, 1), ws.Cells(2, 10))
On Error Resume Next
x1 = -1: x2 = -1: x3 = -1
GetPolynomialRegressionCoefficients rXs, rYs, x1, x2, x3
'
' Get Error message dialog:
'
' Microsoft Visual Basic
' Run-time error '1004':
' Unable to get the LinEst property of the WorksheetFunction class
'
If Err <> 0 Then
Debug.Print "Error Using Rows "; Err; " "; Err.Description
Else
Debug.Print "With data in rows, x1 = "; x1; ", x2 = "; x2; ", x3 = "; x3
End If
End Sub
最后,这里是我的例程的完整版本以及调试和验证代码。仅供参考(请不要批评):
Sub-getpolynomialregressioncoverties(Xs作为Excel.Range,Ys作为Excel.Range,ByRef x1作为Double,ByRef x2作为Double,ByRef x3作为Double)
'
'计算存储在Xs和Ys范围内的数据的最佳拟合系数
'
Dim rgCoeff’这将是一个为最佳拟合二次曲线计算的系数的可变数组
#如果RELEASE=0,则
Dim iRow As Long“仅用于调试目的。
Dim iCol作为“长”仅用于调试目的。
'
'确认范围大小相同。
'
如果是(Xs.Rows.Count Ys.Rows.Count)和(Xs.Columns.Count Ys.Columns.Count),则停止
'
'确认范围中的所有数据都是数字,而不是空白
'
对于iRow=1到Ys.Rows.Count
对于iCol=1到Xs.Columns.Count
如果IsNumeric(Xs.Cells(iRow,iCol))=False或IsNumeric(Ys.Cells(iRow,iCol))=False或Trim(Xs.Cells(iRow,iCol))=“”或Trim(Ys.Cells(iRow,iCol))=“”则停止
下一个iCol
下一步
多芬特
#如果结束
rgCoeff=Application.WorksheetFunction.LinEst(Ys,Application.Power(Xs,数组(1,2)))
x1=rgCoeff(1)
x2=rgCoeff(2)
x3=rgCoeff(3)
端接头
TLDR:对于行中的数据,您需要使用数组(数组(1),数组(2))
而不是数组(1,2)
问题不在于
工作表函数.LinEst
函数,而在于应用程序.Power
函数。要检查这一点,可以添加名为XsArray的中间变量,如下所示:
Sub GetPolynomialRegressionCoefficients(Xs As Excel.Range, Ys As Excel.Range, ByRef x1 As Double, ByRef x2 As Double, ByRef x3 As Double)
'
' Calculates the best fit coefficients of the data stored in ranges Xs and Ys
'
Dim rgCoeff ' This will be a variant array of the coefficients calculated for the best fit quadratic curve
Dim XsArray As Variant
XsArray = Application.Power(Xs, Array(1, 2))
rgCoeff = Application.WorksheetFunction.LinEst(Ys, XsArray)
x1 = rgCoeff(1)
x2 = rgCoeff(2)
x3 = rgCoeff(3)
End Sub
Sub GetPolynomialRegressionCoefficients(Xs As Excel.Range, Ys As Excel.Range, ByRef x1 As Double, ByRef x2 As Double, ByRef x3 As Double)
'
' Calculates the best fit coefficients of the data stored in ranges Xs and Ys
'
Dim rgCoeff ' This will be a variant array of the coefficients calculated for the best fit quadratic curve
Dim XsArray As Variant
If Xs.Rows.Count > Xs.Columns.Count Then
XsArray = Application.Power(Xs, Array(1, 2))
Else
XsArray = Application.Power(Xs, Array(Array(1), Array(2)))
End If
rgCoeff = Application.WorksheetFunction.LinEst(Ys, XsArray)
x1 = rgCoeff(1)
x2 = rgCoeff(2)
x3 = rgCoeff(3)
End Sub
如果您打开本地窗口(放置断点后),您将看到这就是错误的来源:
我找不到关于这一点的任何好的现有解释,但我理解它的方式是幂函数有点像矩阵乘法:你要么想要一个行矩阵乘以一个列矩阵,要么反之亦然,你不想要两个行矩阵或两个列矩阵
这里的问题是Array(1,2)
被VBA视为行矩阵,因为它是一个简单的1D数组。因此,当Xs
是一个“列范围”时,一切都很好,但当它是一个“行范围”时,我们需要传递一些可以被视为列矩阵的内容。实现这一目标的一种方法是:
Sub GetPolynomialRegressionCoefficients(Xs As Excel.Range, Ys As Excel.Range, ByRef x1 As Double, ByRef x2 As Double, ByRef x3 As Double)
'
' Calculates the best fit coefficients of the data stored in ranges Xs and Ys
'
Dim rgCoeff ' This will be a variant array of the coefficients calculated for the best fit quadratic curve
Dim XsArray As Variant
XsArray = Application.Power(Xs, Array(1, 2))
rgCoeff = Application.WorksheetFunction.LinEst(Ys, XsArray)
x1 = rgCoeff(1)
x2 = rgCoeff(2)
x3 = rgCoeff(3)
End Sub
Sub GetPolynomialRegressionCoefficients(Xs As Excel.Range, Ys As Excel.Range, ByRef x1 As Double, ByRef x2 As Double, ByRef x3 As Double)
'
' Calculates the best fit coefficients of the data stored in ranges Xs and Ys
'
Dim rgCoeff ' This will be a variant array of the coefficients calculated for the best fit quadratic curve
Dim XsArray As Variant
If Xs.Rows.Count > Xs.Columns.Count Then
XsArray = Application.Power(Xs, Array(1, 2))
Else
XsArray = Application.Power(Xs, Array(Array(1), Array(2)))
End If
rgCoeff = Application.WorksheetFunction.LinEst(Ys, XsArray)
x1 = rgCoeff(1)
x2 = rgCoeff(2)
x3 = rgCoeff(3)
End Sub
解释
表达式Array(Array(1),Array(2))
返回一个参差不齐的数组,但据我所知,由于它需要两个索引来返回一个元素,VBA将类似地将其解释为二维数组,这些索引将被视为(列)矩阵的坐标:(0,0)和(1,0)
或者
如果不喜欢锯齿状阵列,则始终可以创建带有循环的真实二维阵列:
Dim XsArray As Variant, PowersArray As Variant
If Xs.Rows.Count > Xs.Columns.Count Then
PowersArray = Array(1, 2)
XsArray = Application.Power(Xs, PowersArray)
Else
ReDim PowersArray(0 To 1, 0)
Dim i As Integer
For i = 0 To 1
PowersArray(i, 0) = i + 1
Next i
XsArray = Application.Power(Xs, PowersArray)
End If
谢谢QHarr,我看到了你的评论,虽然它告诉我它被删除了。我不确定我是否理解你的意图。你是说如果我把数据放在行中,而不是列中,我必须使用你描述的方法吗?当数据在列中时,我当前的方法非常有效。我只是不明白为什么同样的方法不能在行中工作。一个更好的解释出现了。但是看起来,就像我删除的消息一样,数组(1,2)需要更改。天哪,你的答案很完美,我已经确认了好几次了。多亏了您的洞察力,我将发布我的例程的更新版本,无论是行还是列都能正常工作@SixSigmaGuy–我很高兴这对我很有帮助!顺便说一句,我没有直接引用它,但我个人使用了一个带有条件的if语句
Xs.Rows.Count>Xs.Columns.Count
,以检查它是一行还是一列(以防有用)。而且,听起来我的回答解决了你的问题,但你还没有接受。我有什么遗漏吗?关于接受它。对不起,我想是的。我有now@SixSigmaGuy–无需担心额外的编辑内容。谢谢