Страницы: 1
RSS
PQ ListGenerate есть ли возможность прервать цикл, или создать лист определенных значений из сгенерированного списка
 
Добрый день.
Изучаю List.Generate
Вчера возникла необходимость подсчитать нарастающий итог, вернее даже не так, нужно было просто получить сумму ряда.
Решил создать ряд, а также нарастающие итоги по ряду с помощью ListGenerate.
Вот кусочек кода, сам фаил выкладывать смысла особого не вижу, он более 60 мегабайт.
Код
ComTotal = Table.AddColumn(Table.Buffer(#"Развернутый элемент Выбытие"), "ComTot", (OT)=>(
List.Generate(
()=>
[i=Number.From(List.Min(OT[Join][Value])  ) , total=OT[Join][Сумма]{0} , j=0, ost = total / OT[Выбытие][Сумма]{0} , OstTotal=total/OT[Выбытие][Сумма]{0}, maxT =0]   , 
each [i]<=Number.From(List.Max(OT[Join][Value]) ),
each [ 
i=[i]+1 , 
j = [j]+1, 
total=List.Sum({Number.From(OT[Join][Сумма]{j}) , Number.From([total])}) ,
ost = total/OT[Выбытие] ,
OstTotal=List.Sum({[OstTotal],[ost]}),
maxT =  if i=Number.From (List.Max(OT[Join][Value])) then (OstTotal) else 0],

each [ 
//ostT=[OstTotal],
//ost = [ost],
//maxT =  [
maxT//],
//i=Date.From([i]) ,
//Классификатор=OT[Классификатор] 
]


Весь этот код тормозит очень сильно, вернее даже не так, тормоза и зависание, и даже переполнение стека, начинается после того, как пробуем работать с результатом выданным list.generate.
По сути мне нужно было получить одно единственное значение Последний элемент ряда в переменной сгенерированной через ЛистГенерейт.
Вопрос, возможно ли как-то получить последний член ряда внутри самой функции?
Не с помощью обертки List.Last( List.Generate()) а именно, непосредственно внутри самой функции как получить последний элемент и оставить его записав в переменную не создавая записи на предыдущем шаге.
Код
List.Generate(
()=>
[i=0],
each [i]<=10,
each i
)

По сути как получить только значение 10 в сгенерированном списке, выкинув все остальное. Это возможно? List.Generate  позволяет хоть как-то контролировать результат? Можно ли прервать счетчик, либо получить значение только 5го-8го члена ряда, или последнего?
Изменено: lostandleft - 09.06.2020 07:08:10
 
А может в данном случае не нужен List.Generate? Покажите в примере исходные данные и результат, с описанием логики расчета.
Вот горшок пустой, он предмет простой...
 
Господа, за третий день опять столкнулся с тойже проблемой...боль и страдания, страдания и боль...и страдания.
Фаил пример во вложении.
В задаче нужно найти сумму К в сгенерированной таблице - К - это сумма полученных коэффициентов. В частном случае К отражет сколько дней был товар на складе.

Пример небольшой, но он наглухо вешает мою машину. На столько сильно, что я даже не стал формировать итоговую таблицу, считает очень долго.
Все запросы в примере приложены.
Прошу оценить масштаб бедствия.

Я могу добавить еще одну колонку в сгенерированный список - нарастающий итог по коэффициенту, например. Есть ли возможность показать только последний член ряда через функцию листгенерейт? Показать в итоге только самый последний итого, по нарастающему итогу?
Изменено: lostandleft - 11.06.2020 13:29:43
 
Не совсем понял чего надо, вдруг угадал.
Код Power Query:
Код
let
   Source          = Excel.CurrentWorkbook(){[Name = "Движение"]}[Content],
   #"Grouped Rows" = Table.Group(
       Source,
       {"название"},
       {
           {
               "_",
               each
                   let
                       t   = Table.Buffer(_),
                       l   = List.Buffer(t[Движение]),
                       gen = List.Generate(
                           () => [i = 0, j = 1, sum = l{i}],
                           each [i] < List.Count(l),
                           each [i = [i] + 1, j = if [sum] = 0 then 1 else 0, sum = [sum] + l{i}],
                           each if [i] = 0 then 1 else [j]
                       ),
                       gr  = Table.Group(
                           Table.FromColumns({gen} & Table.ToColumns(t)),
                           {"Column1"},
                           {
                               "a",
                               each Duration.TotalDays(List.Max([Column2]) - List.Min([Column2]))
                           },
                           0,
                           (a, b) => b[Column1]
                       )
                   in
                       List.Sum(gr[a]),
               Int64.Type
           }
       }
   )
in
   #"Grouped Rows"
 
Андрей Лящук,
Хотя нет, если поменять количества результат должен быть иной.
В данном случае не задача просчитать разницу дней!!!
задача просчитать сумму ряда.
Сумма ряда считается так.
Берем остаток на каждый день между датой отгрузки/отправки/оплаты и делим этот остаток на общую сумму.

Таким образом, если я меняют последнюю цифру, делаю или больше, или меньше, в любом случае если цифра поступления не равна цифре выбытия, то в любом случае 900 не получится.
В любом случае будет разница 897-905 и так далее.

Задача - просчитать сумму К. На фотографии ниже, показан результат, просчитал таки его мой ПК. Правая картинка. Ваша показывает 900 всегда и везде.
Так быть не должно
Код
= Table.AddColumn(
#"Добавлен пользовательский объект", "Generate", (OT)=>
List.Generate( ()=>
[i=Number.From(List.Min(OT[Движение][Column1])  ) , j=0, sum = OT[Движение][Движение]{j} , k=sum/List.Sum(OT[Движение][Выбытие])  ],
each [i]<=Number.From(List.Max(OT[Движение][Column1])),
each [i = [i]+1 , j=[j]+1  , sum = List.Sum({ [sum] ,  OT[Движение][Движение]{j} }) , k = [sum] / List.Sum(OT[Движение][Выбытие])  ],
each [i=[i],sum=[sum] , j=[j] , k=[k]]


)
)
Изменено: lostandleft - 11.06.2020 15:45:37
 
Доброе время суток
Цитата
lostandleft написал:
Сумма ряда считается так.
Берем остаток на каждый день между датой отгрузки/отправки/оплаты и делим этот остаток на общую сумму.
Позвольте поинтересоваться, какое отношение разность, делённая на некоторое постоянное число, имеет к сумме ряда? В вашей таблице нигде нет слов отгрузка, отправка, оплата, тогда зачем их употреблять в описании чего-нибудь? Или приведите каким словам таблицы они соответствуют? Синонимы хороши в литературном произведении :)
Не могли бы вы, не прибегая ни к формулам Excel, ни к функциям Power Query описать алгоритм расчёта?
Изменено: Андрей VG - 12.06.2020 07:38:58
 
Цитата
Андрей VG написал:
Не могли бы вы, не прибегая ни к формулам Excel, ни к функциям Power Query описать алгоритм расчёта?
Добрый день! Спасибо за интерес к теме.
Общая схема расчета выглядит так:
Код
День 1 (i=1):  ОстатокНач + Приход1 - Расход1 = ОстатокКон.
День 2 (i=2):  ОстатокНач + Приход2 - Расход2 = ОстатокКон.
День 3 (i=3):  ОстатокНач + Приход3 - Расход3 = ОстатокКон.
ИтогоРасход=Расход1+Расход2+Расход3

к1= ОстатокКон(i1) / ИтогоРасход
к2= ОстатокКон(i2) / ИтогоРасход
к3= ОстатокКон(i3) / ИтогоРасход

Кобщ =k1 + k2 +k3 - его нужно найти.

i - это дни периода, в какие-то дни периода операции Приход и Расход могут быть, а в какие-то дни периода этих операций быть не может.
Однако остаток, может присутсвовать.
Т.е. в теории в день 2 остаток начальный и конечный будут равными друг другу, при этом приход и расход будут равны нулю.

Этот порядок - базовый подход в расчете среднего остатка чего-либо, в единицах измерения заданных в i  
Изменено: lostandleft - 12.06.2020 10:28:37
 
Цитата
lostandleft написал:
i - это дни периода, в какие-то дни периода операции
Без относительно к персику, свекле и т. д.?
 
Андрей VG,
Для персика, свеклы, огруца и гвоздя i - свое.
Для каждого ТМЦ схема одна, однако расчет индивидуальный.
Именно это и реализовано в моих запросах .
Создается отдельная таблица для каждого ТМЦ в которую подгружается i - период, из календаря и индивидуальное движение (приход-расход) каждой позиции.
Для каждой позиции создается свой ListGenerate и делается индивидуальный расчет.
Т.е. для каждой позиции индивидуально берется алгоритм описанный выше
Изменено: lostandleft - 12.06.2020 11:03:24
 
Цитата
lostandleft написал:
Для персика, свеклы, огруца и гвоздя i - свое.
Добро. Пусть столбец таблицы Поступление соответствует в описании вычислений Приход, а  Выбытие - Расход. Тогда что такое ОстатокНач?
Далее, по приведённым вами формулам выполним предобразования
Код
Кобщ =k1 + k2 +k3
Кобщ = (ОстатокКон(i1) + ОстатокКон(i2) + ОстатокКон(i3)) / ИтогоРасход
Кобщ = (ОстатокНач + Приход1 - Расход1 + ОстатокНач + Приход2 - Расход2 + ОстатокНач + Приход3 - Расход3) / ИтогоРасход
Кобщ = (N * ОстатокНач + ∑ Приход - ∑ Расход) / ИтогРасход
Кобщ = (N * ОстатокНач + ∑ Приход - ∑ Расход) / ∑ Расход

Для персика есть один Приход 500 и один Расход 500. Пусть ОстатокНач = 0. Тогда подставим получим Кобщ = (0 + 500 - 500) / 500 = 0. А у вас на рисунке 1179, тогда правильна ли предложенная вами методика расчёта?
 
Андрей VG,
Методика расчета правильная и корректная.
Если операция совершена внутри одного дня то к итоговый будет равен 0.
Так и должно быть. Если же операция совершена в разные интервалы времени.
Как это отражено в моей таблице, то К совершенно не будет равным нулю.
Вы купили персик, 500 шт. Положили его в холодильник. Остаток в холодильнике 500, приход = 500
Т.е. ОстатокН (0) + Приход (500)-Расход(0).
Кушать Вы его не стали, на следующий день съели 250 персиков.
Он(500)+Приход(0)-Расход(250) Ок=(250)
День три, подумали еще раз и решили доесть персики, остаток по итогу дня будет 0
Он(250)+Приход(0)-Расход(250) Ок=(0)

Больше персики Вы не покупали.
Просчитаем средний период товарного остатка персиков в днях в Вашем холодильнике:
к1 = Ок1 (500) / СуммаР(500) = 1
к2 = Ок2(250)/500 = 0,5
к3 = Ок3(0)/500 = 0
Итого К =  1+0,5+0 = 1,5.
Делаем Вывод что средний размер товарного остатка персиков в Вашем холодильнике равен 1,5 дням его употребления.

У меня на рисунке ДНИ СОВСЕМ ДРУГИЕ - интервал i - обратите внимание на Даты!!!!

Расчет корректный, господа давайте по сути, нужна сумма ряда К в расчетах. Для каждой товарной позиции.
Методика расчета не требует обсуждения.
Изменено: lostandleft - 12.06.2020 11:32:13
 
Цитата
lostandleft написал:
Методика расчета не требует обсуждения.
Точно?
В вашей нотации
День 1 (i=1):  ОстатокНач + Приход1 - Расход1 = ОстатокКон.
День 1 (i=1):  0+ 500 - 0
День 2 (i=2):  ОстатокНач + Приход2 - Расход2 = ОстатокКон.
День 2 (i=2):  0+ 0- 250
День 3 (i=3):  ОстатокНач + Приход3 - Расход3 = ОстатокКон.
День 3 (i=3):  0 + 0 - 250
А вы что делаете? Вместо ОстатокНач  и Приход подставляете предыдущее состояние и утверждаете, что всё правильно вы написали в формулировке вычислений. Ваше право - ваша методика - ваша интерпретация ваше решение. Это всё же вам нужно.
Успехов.
 
13.10.13 купили 726 морковин, заморозили, 900 дней не трогали, на протяжении этих дней остаток неизменен и = 726
на 901 день сожрали 500 морковин, осталось 226
ИтогоРасход = 500
тогда по вашей схеме расчета должно получиться
откуда взялись ваши 1179?
Изменено: Андрей Лящук - 12.06.2020 11:51:47
 
Цитата
Андрей Лящук написал:
тогда по вашей схеме расчета должно получиться
Обратите внимание, период заканчивается несколько позже, анализируемый период заканчивается не через 900 дней!!!!!!
Обратите внимание на ПЕРИОД!!!!!
Общий период с 01-05-12 по 05-01-17
Таким образом, не смотря на то, что мы сожрали 500 морковок, на остатке у нас остается еще 226 штук, которые продолжают лежать в замороженном виде вплоть до 05-01-17.
Период не равен 900 дням по данной позиции!
 
ок, еще 271 день остаток = 226, итого
Код
(900*726+271*226)/500=1429,292
 
Андрей Лящук,
Практически тоже самое и нарисовано на моей картинке.
Видимо какие-то округления не проходят.
Как все тоже самое реализовать для каждой позиции индивидуально, в PQ с учетом того, что период для каждой из них будет различным?
Более того, операций может быть тясячи.
Изменено: lostandleft - 12.06.2020 12:32:04
 
Цитата
Андрей VG написал:
День 1 (i=1):  ОстатокНач + Приход1 - Расход1 = ОстатокКон.День 1 (i=1):  0+ 500 - 0 День 2 (i=2):  ОстатокНач + Приход2 - Расход2 = ОстатокКон.День 2 (i=2):  0+ 0- 250 День 3 (i=3):  ОстатокНач + Приход3 - Расход3 = ОстатокКон.День 3 (i=3):  0 + 0 - 250
До меня только-только дошло что именно Вам не понятно.
Это назвается когда очевидные вещи для тебя, есть более чем неочевидные для окружающих.
Остаток на начало каждого дня свой, и он равен остатку предыдущего дня на конец.
В экселевской табличке это показал отдельно.
Андрей Лящук,  понял меня более-менее корректно сразу :-).
1 день - разница в его расчетах и в моих видимо первый день. Но это уже детали интерпретаций, что считать первым днем цикла. Если морковь или персик купили вечером, полный ли это день, или это уже вечер и начало следующего дня, а если их купили и положили на склад утром ....в общем 1 день роли не играет по сути.
Чтобы было понятнее еще раз:
Код
День 1 (i=1):  ОстатокНач1 + Приход1 - Расход1 = ОстатокКон1.
День 2 (i=2):  ОстатокНач2 + Приход2 - Расход2 = ОстатокКон2.
День 3 (i=3):  ОстатокНач3 + Приход3 - Расход3 = ОстатокКон3.
ИтогоРасход=Расход1+Расход2+Расход3

ОстатокНач2 =ОстатокКон1,
ОстатокНач3 = ОстатокКон2
 
к1= ОстатокКон(i1) / ИтогоРасход
к2= ОстатокКон(i2) / ИтогоРасход
к3= ОстатокКон(i3) / ИтогоРасход
 
Кобщ =k1 + k2 +k3 - его нужно найти.
Изменено: lostandleft - 12.06.2020 12:57:38
 
Цитата
lostandleft написал:
Остаток на начало каждого дня свой, и он равен остатку предыдущего дня на конец.
Ну, наконец-то ТЗ приобрело человеческий вид :)  Ещё бы определения в таблице сбить с используемым в формулах.
Вариант.
Код
let
    Source = Excel.CurrentWorkbook(){[Name="Движение"]}[Content],
    typed = Table.TransformColumnTypes(Source,{{"Дата", type date}, {"название", type text}, {"Поступление", Int64.Type}, {"Выбытие", Int64.Type}, {"Движение", Int64.Type}}),
    maxDate = List.Max(typed[Дата]),
    maker = Table.Group(typed, {"название"}, {"value", each
        let
            calcBase = Table.AddColumn(_, "temp", each (Duration.TotalDays(maxDate - [Дата]) + 1) * List.Sum({[Поступление], -[Выбытие]})),
            outValue = Number.Abs(List.Sum(calcBase[Выбытие])),
            allSum = List.Sum(calcBase[temp])
        in
            allSum / outValue
    })
in
    maker
 
Андрей VG,
Андрей, я плачу, каким образом все это работает и так быстро. Пока не понимаю

ListGenerate вообще не используется
Изменено: lostandleft - 12.06.2020 13:03:35
 
Цитата
lostandleft написал:
ListGenerate вообще не используется
А зачем оно, если можно воспользоваться школьным курсом - упростить выражение?
 
Цитата
Андрей VG написал: А зачем оно
Стереотип мышления  :cry:

Андрей VG, Вы не могли бы пояснить для чего мы вкладываем еще один
let in
Внутрь кода, внутрь Table.Group
Это как-то увеличивает быстродействие?
 
Цитата
lostandleft написал:
не могли бы пояснить
Уже описано, достаточно прочитать Выражение let, не вырабатывайте странные стереотипы :)
Страницы: 1
Наверх