let f=(x,y)=> y{0}+y{1}*x, g=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Segment,{"ID"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Segment"}, {y{1}})][b], h=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Rating,{"Rating"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Шкала"}, {y{1}})][b], j=(x,y)=>[ a = List.Zip({Table.Column(x,y),x[#"Average Шкала"]}), b = List.Accumulate(a,[n=0,x=0,x2=0,y=0,xy=0],(s,c)=>[n=s[n]+1,x=s[x]+c{0},x2=s[x2]+c{0}*c{0},y=s[y]+c{1},xy=s[xy]+c{0}*c{1}]), c = [i=(b[n]*b[xy]-b[x]*b[y])/(b[n]*b[x2]-b[x]*b[x]),j=(b[y]-i*b[x])/b[n]], d = {c[j],c[i]}][d], k=(x)=>if Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") then {x,0} else if Text.Contains(x,"долг") then {x,10000} else {x,null}, l=(x,y)=>[ a = List.Buffer(j(x,y)), b = Table.AddColumn(x,"Forecast "&y,(r)=> f(Record.Field(r,y),a))][b],
from = Excel.CurrentWorkbook(){[Name="Issuers"]}[Content], tcn = Table.ColumnNames(from), nms = List.Transform(tcn,k), rep = Table.ReplaceErrorValues(from, nms), seg = g(rep,{"ID","Segment"}), lst = {{"S&P","Шкала S"},{"Moody`s","Шкала M"},{"Fitch","Шкала F"}}, rtg = List.Accumulate(lst,seg,h), add = Table.AddColumn(rtg, "Average Шкала", each List.Average({[Шкала S], [Шкала M], [Шкала F]})), fcn = List.Select(tcn,(x)=>Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") or Text.Contains(x,"долг") ), to = List.Accumulate(fcn,add,l) in to
let f=(x,y)=> y{0}+y{1}*x, g=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Segment,{"ID"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Segment"}, {y{1}})][b], h=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Rating,{"Rating"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Шкала"}, {y{1}})][b], j=(x,y)=>[ a = List.Zip({Table.Column(x,y),x[#"Average Шкала"]}), b = List.Accumulate(a,[n=0,x=0,x2=0,y=0,xy=0],(s,c)=>[n=s[n]+1,x=s[x]+c{0},x2=s[x2]+c{0}*c{0},y=s[y]+c{1},xy=s[xy]+c{0}*c{1}]), c = [i=(b[n]*b[xy]-b[x]*b[y])/(b[n]*b[x2]-b[x]*b[x]),j=(b[y]-i*b[x])/b[n]], d = {c[j],c[i]}][d], k=(x)=>if Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") then {x,0} else if Text.Contains(x,"долг") then {x,10000} else {x,null}, l=(x,y)=>[ a = List.Buffer(j(x,y)), b = Table.AddColumn(x,"Forecast "&y,(r)=> f(Record.Field(r,y),a))][b],
from = Excel.CurrentWorkbook(){[Name="Issuers"]}[Content], tcn = Table.ColumnNames(from), nms = List.Transform(tcn,k), rep = Table.ReplaceErrorValues(from, nms), seg = g(rep,{"ID","Segment"}), lst = {{"S&P","Шкала S"},{"Moody`s","Шкала M"},{"Fitch","Шкала F"}}, rtg = List.Accumulate(lst,seg,h), add = Table.AddColumn(rtg, "Average Шкала", each List.Average({[Шкала S], [Шкала M], [Шкала F]})), fcn = List.Select(tcn,(x)=>Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") or Text.Contains(x,"долг") ), to = List.Accumulate(fcn,add,l) in to
ну вот и сразу вопросы по живому примеру - что делать с Average Шкала, когда все рейтинги null? Что делать, когда по сегменту одна строчка? сделал как посчитал нужным, допиливайте самостоятельно: [vba]
Код
let f=(x,y)=> y{0}+y{1}*x, g=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Segment,{"ID"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Segment"}, {y{1}})][b], h=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Rating,{"Rating"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Шкала"}, {y{1}})][b], j=(x,y)=>[ a = List.Zip({Table.Column(x,y),x[#"Average Шкала"]}), a1= List.Select(a,(x)=> not (x{0}=null or x{1}=null)), b = List.Accumulate(a1,[n=0,x=0,x2=0,y=0,xy=0],(s,c)=>[n=s[n]+1,x=s[x]+c{0},x2=s[x2]+c{0}*c{0},y=s[y]+c{1},xy=s[xy]+c{0}*c{1}]), c = [i=(b[n]*b[xy]-b[x]*b[y])/(b[n]*b[x2]-b[x]*b[x]),j=(b[y]-i*b[x])/b[n]], d = if List.Count(a1)>1 then {c[j],c[i]} else {0,0}][d], k=(x)=>if Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") then {x,0} else if Text.Contains(x,"долг") then {x,10000} else {x,null}, l=(x,y)=>[ a = List.Buffer(j(x,y)), b = Table.AddColumn(x,"Forecast "&y,(r)=> f(Record.Field(r,y),a))][b], m=(x)=> [ a = List.Transform(x,(x)=> try Number.From(x) otherwise null), b = List.Average(a)][b],
from = Excel.CurrentWorkbook(){[Name="Issuers"]}[Content], tcn = Table.ColumnNames(from), nms = List.Transform(tcn,k), rep = Table.ReplaceErrorValues(from, nms), seg = g(rep,{"ID","Segment"}), lst = {{"S&P","Шкала S"},{"Moody`s","Шкала M"},{"Fitch","Шкала F"}}, rtg = List.Accumulate(lst,seg,h), add = Table.AddColumn(rtg, "Average Шкала", each m({[Шкала S], [Шкала M], [Шкала F]})), fcn = List.Select(tcn,(x)=>Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") or Text.Contains(x,"долг") ), grp = Table.Group(add, "Segment", {"tmp", each List.Accumulate(fcn,_,l)}), to = Table.Combine(grp[tmp]) in to
[/vba]
ну вот и сразу вопросы по живому примеру - что делать с Average Шкала, когда все рейтинги null? Что делать, когда по сегменту одна строчка? сделал как посчитал нужным, допиливайте самостоятельно: [vba]
Код
let f=(x,y)=> y{0}+y{1}*x, g=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Segment,{"ID"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Segment"}, {y{1}})][b], h=(x,y)=>[ a = Table.NestedJoin(x,{y{0}},Rating,{"Rating"},"tmp",JoinKind.LeftOuter), b = Table.ExpandTableColumn(a, "tmp", {"Шкала"}, {y{1}})][b], j=(x,y)=>[ a = List.Zip({Table.Column(x,y),x[#"Average Шкала"]}), a1= List.Select(a,(x)=> not (x{0}=null or x{1}=null)), b = List.Accumulate(a1,[n=0,x=0,x2=0,y=0,xy=0],(s,c)=>[n=s[n]+1,x=s[x]+c{0},x2=s[x2]+c{0}*c{0},y=s[y]+c{1},xy=s[xy]+c{0}*c{1}]), c = [i=(b[n]*b[xy]-b[x]*b[y])/(b[n]*b[x2]-b[x]*b[x]),j=(b[y]-i*b[x])/b[n]], d = if List.Count(a1)>1 then {c[j],c[i]} else {0,0}][d], k=(x)=>if Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") then {x,0} else if Text.Contains(x,"долг") then {x,10000} else {x,null}, l=(x,y)=>[ a = List.Buffer(j(x,y)), b = Table.AddColumn(x,"Forecast "&y,(r)=> f(Record.Field(r,y),a))][b], m=(x)=> [ a = List.Transform(x,(x)=> try Number.From(x) otherwise null), b = List.Average(a)][b],
from = Excel.CurrentWorkbook(){[Name="Issuers"]}[Content], tcn = Table.ColumnNames(from), nms = List.Transform(tcn,k), rep = Table.ReplaceErrorValues(from, nms), seg = g(rep,{"ID","Segment"}), lst = {{"S&P","Шкала S"},{"Moody`s","Шкала M"},{"Fitch","Шкала F"}}, rtg = List.Accumulate(lst,seg,h), add = Table.AddColumn(rtg, "Average Шкала", each m({[Шкала S], [Шкала M], [Шкала F]})), fcn = List.Select(tcn,(x)=>Text.Contains(x,"маржа") or Text.Contains(x,"Дох-ть") or Text.Contains(x,"долг") ), grp = Table.Group(add, "Segment", {"tmp", each List.Accumulate(fcn,_,l)}), to = Table.Combine(grp[tmp]) in to