Power BI中的多元线性回归

时间:2018-02-14 21:53:48

标签: excel-formula linear-regression powerbi dax

假设我有一组回报,我想计算其β值与不同的市场指数。为了有一个具体的例子,让我们在名为Returns的表中使用以下数据集:

  Date       Equity  Duration  Credit  Manager
-----------------------------------------------
01/31/2017   2.907%   0.226%   1.240%   1.78%
02/28/2017   2.513%   0.493%   1.120%   3.88%
03/31/2017   1.346%  -0.046%  -0.250%   0.13%
04/30/2017   1.612%   0.695%   0.620%   1.04%
05/31/2017   2.209%   0.653%   0.480%   1.40%
06/30/2017   0.796%  -0.162%   0.350%   0.63%
07/31/2017   2.733%   0.167%   0.830%   2.06%
08/31/2017   0.401%   1.083%  -0.670%   0.29%
09/30/2017   1.880%  -0.857%   1.430%   2.04%
10/31/2017   2.151%  -0.121%   0.510%   2.33%
11/30/2017   2.020%  -0.137%  -0.020%   3.06%
12/31/2017   1.454%   0.309%   0.230%   1.28%

现在在Excel中,我可以使用LINEST函数来获取beta值:

= LINEST(Returns[Manager], Returns[[Equity]:[Credit]], TRUE, TRUE)

它吐出一个如下所示的数组:

0.077250253 -0.184974002  0.961578127 -0.001063971
0.707796954  0.60202895   0.540811546  0.008257129
0.50202386   0.009166729  #N/A         #N/A
2.688342242  8            #N/A         #N/A
0.000677695  0.000672231  #N/A         #N/A

测试版位于顶行并使用它们给出了以下线性估计值:

Manager = 0.962 * Equity - 0.185 * Duration + 0.077 * Credit - 0.001

问题是如何使用DAX在Power BI中获取这些值(最好不必编写自定义R脚本)?

对于一列的simple linear regression,我可以回到数学定义并编写一个类似于this post中给出的最小二乘实现。

然而,当涉及更多列时(我需要能够最多12列,但并不总是相同的数字),这很快就会变得混乱,我希望有更好的方法

2 个答案:

答案 0 :(得分:2)

由于Power BI中LINEST函数没有等效或方便的替换(我确定你在发布问题之前已经做了足够的研究),任何尝试都意味着在Power Query /中重写整个函数M,对于简单线性回归的情况来说已经不是那么“简单”,更不用说多个变量了。

而不是(重新)发明轮子,在Power BI中使用R脚本执行它不可避免地更容易(单行代码..)。

鉴于我之前没有R经验,这不是一个糟糕的选择。经过几次搜索和反复试验后,我能够想出这个:

# 'dataset' holds the input data for this script
# install.packages("broom") # uncomment to install if package does not exist
library(broom)

model <- lm(Manager ~ Equity + Duration + Credit, dataset)
model <- tidy(model)

lm是来自R的内置linear model functiontidy函数附带broom包,tidies up the output and output a data frame用于Power BI。< / p>

result

使用列termestimate,这应该足以计算您想要的估算值。

M查询供您参考:

let
    Source = Csv.Document(File.Contents("returns.csv"),[Delimiter=",", Columns=5, Encoding=1252, QuoteStyle=QuoteStyle.None]),
    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"Date", type text}, {"Equity", Percentage.Type}, {"Duration", Percentage.Type}, {"Credit", Percentage.Type}, {"Manager", Percentage.Type}}),
    #"Run R Script" = R.Execute("# 'dataset' holds the input data for this script#(lf)# install.packages(""broom"")#(lf)library(broom)#(lf)#(lf)model <- lm(Manager ~ Equity + Duration + Credit, dataset)#(lf)model <- tidy(model)",[dataset=#"Changed Type"]),
    #"""model""" = #"Run R Script"{[Name="model"]}[Value]
in
    #"""model"""

答案 1 :(得分:0)

我已经想出了如何专门针对三个变量执行此操作,但这种方法根本无法放大或缩小到更多或更少的变量。

Regression = 
VAR ShortNames =
    SELECTCOLUMNS (
        Returns,
        "A", [Equity],
        "D", [Duration],
        "C", [Credit],
        "Y", [Manager]
    )
VAR n = COUNTROWS ( ShortNames )

VAR A = SUMX ( ShortNames, [A] )
VAR D = SUMX ( ShortNames, [D] )
VAR C = SUMX ( ShortNames, [C] )
VAR Y = SUMX ( ShortNames, [Y] )

VAR AA = SUMX ( ShortNames, [A] * [A] ) - A * A / n
VAR DD = SUMX ( ShortNames, [D] * [D] ) - D * D / n
VAR CC = SUMX ( ShortNames, [C] * [C] ) - C * C / n

VAR AD = SUMX ( ShortNames, [A] * [D] ) - A * D / n
VAR AC = SUMX ( ShortNames, [A] * [C] ) - A * C / n
VAR DC = SUMX ( ShortNames, [D] * [C] ) - D * C / n

VAR AY = SUMX ( ShortNames, [A] * [Y] ) - A * Y / n
VAR DY = SUMX ( ShortNames, [D] * [Y] ) - D * Y / n
VAR CY = SUMX ( ShortNames, [C] * [Y] ) - C * Y / n

VAR BetaA =
    DIVIDE (
        AY*DC*DC - AD*CY*DC - AY*CC*DD + AC*CY*DD + AD*CC*DY - AC*DC*DY,
        AD*CC*AD - AC*DC*AD - AD*AC*DC + AA*DC*DC + AC*AC*DD - AA*CC*DD
    )
VAR BetaD =
    DIVIDE (
        AY*CC*AD - AC*CY*AD - AY*AC*DC + AA*CY*DC + AC*AC*DY - AA*CC*DY,
        AD*CC*AD - AC*DC*AD - AD*AC*DC + AA*DC*DC + AC*AC*DD - AA*CC*DD
    )
VAR BetaC =
    DIVIDE (
      - AY*DC*AD + AD*CY*AD + AY*AC*DD - AA*CY*DD - AD*AC*DY + AA*DC*DY,
        AD*CC*AD - AC*DC*AD - AD*AC*DC + AA*DC*DC + AC*AC*DD - AA*CC*DD
    )
VAR Intercept =
    AVERAGEX ( ShortNames, [Y] )
        - AVERAGEX ( ShortNames, [A] ) * BetaA
        - AVERAGEX ( ShortNames, [D] ) * BetaD
        - AVERAGEX ( ShortNames, [C] ) * BetaC
RETURN
        { BetaA, BetaD, BetaC, Intercept }

这是一个计算表,返回指定的回归系数:

Calculated Table

这些数字与所提供数据的 LINEST 输出相匹配。

注意:我在问题中引用的 LINEST 值与这些值略有不同,因为它们是根据未四舍五入的回报计算的,而不是问题中提供的四舍五入的回报。


我参考了 this document 的计算设置和 Mathematica 来解决系统:

enter image description here