ABC-анализ на М

#АнатомияФункций – приёмы



Все привет!

Как насчёт задачки, чтоб аккумулятор с генератором, сортировками, группировками,буферами и комбайнами всякими?

Ну вот примерно такое и требуется, если ABC-анализ проводить на стороне PQ, да чтоб сразу по пачке столбцов, с сохранением порядка строк, блекджеком и … (хотя, когда закончите – они тоже не помешают).



В общем когда-то давно, на заре Мерки, я решил это так:

(таблица,группа,столбцы)=>

let

ABC=(tbl,col,colname)=>[

t = Table.Buffer(Table.Sort(tbl,{col,Order.Descending})),

r = List.Buffer(Table.Column(t,col)),

n = List.Count(r),s = List.Sum(r),

a = 0.5*s,b = 0.8*s,c = 0.95*s,

f=(x)=>if x<=a then "A" else if x<=b then "B" else if x<=c then "C" else "D",

g = List.Generate(()=>[i=0,j=r{i},k="A"],(x)=>x[i]<n,(x)=>[i=x[i]+1,j=r{i}+x[j],k=f(j)],(x)=>x[k]),

res = Table.FromColumns(Table.ToColumns(t)&{g},Table.ColumnNames(t)&{colname})][res],

add = Table.AddIndexColumn(таблица,"i"),

lst = List.Buffer(List.Transform(столбцы,(x)=>{x,"ABC_"&x})),

g=(tbl)=>List.Accumulate(lst,tbl,(s,c)=>ABC(s,c{0},c{1})),

gr=Table.Group(add,группа,{"t",g}),

exp = Table.ExpandTableColumn(gr,"t",List.Combine(lst)&{"i"}),

to = Table.RemoveColumns(Table.Sort(exp,"i"),"i")

in

to


Ну решил и забыл. А тут неожиданно в чат принесли код на оптимизацию, и я начал его переписывать… закрались сомнения – полез в архивы – понял, что переписываю сам себя из 2020 ))) Вот только переписать всё равно было необходимо, поэтому получилось такое:

(таблица,группа,столбцы)=>

[

ABC=(tbl,col,colname)=>[

t = Table.Buffer(Table.Sort(tbl,{col,Order.Descending})),

r = List.Buffer(Table.Column(t,col)),

n = List.Count(r),s = List.Sum(r),

a = g(0.5*s), b = g(0.8*s), c = g(0.95*s),

f=(x)=>if x<=a or x=0 then "A" else if x<=b then "B" else if x<=c then "C" else "D",

gen = List.Buffer(List.Generate(()=>[i=0,j=r{i}],(x)=>x[i]<n,(x)=>[i=x[i]+1,j=r{i}+x[j]],(x)=>x[j])),

g=(x)=>List.PositionOf(gen,x,Occurrence.Last,(c,v)=>v>=c),

res = Table.TransformColumns(Table.AddIndexColumn(t,colname),{colname,f})][res],

add = Table.AddIndexColumn(таблица,"i"),

lst = List.Buffer(List.Transform(столбцы,(x)=>{x,"ABC_"&x})),

g=(tbl)=>List.Accumulate(lst,tbl,(s,c)=>ABC(s,c{0},c{1})),

gr=Table.Group(add,группа,{"t",g}),

exp = Table.Combine(gr[t]),

to = Table.RemoveColumns(Table.Sort(exp,"i"),"i")][to]


Если думаете, что это практически тоже самое – ошибаетесь, оно отличается алгоритмически и при этом кратно шустрее )))



Ну а детали можно посмотреть:

На спонсоре с исходниками

На рутубе

На дзене

На ютубе



Лайк, коммент, подписка приветствуются )))



Надеюсь, было полезно.

Всех благ!

@buchlotnik