Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
RSS
Функции Power Query, которые ведут себя неоднозначно, и вообще возомнили о себе
 
Навеяно неоднократными вопросами об изменении порядка строк после выполнения функции, например этой
Цитата
Михаил Л написал:
Впору в курилке создать тему про функции PQ, которые не ведут себя однозначно при разных количествах строк.

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

точно не гарантирует сохранение порядка строк:
  1. глобальная группировка
  2. удаление дубликатов
  3. слияние/join/merge (практически любой вариант слияния)
Скорее всего, не гарантирует порядок строк
  1. удаление дубликатов списка (List.Distinct) (но не проверял, х.з., не помню, почему мне так кажется, но кажется логичным).
  2. разворачивание структурного столбца в новые строки:
    • Table.ExpandRecordColumn (столбец записей),
    • Table.ExpandListColumn (столбец списков),
    • Table.ExpandTableColumn столбец таблиц)
Локальная группировка, по идее, должна сохранять порядок строк, но не сильно удивлюсь, если при правильно проведенной локальной группировке порядок вывода результата будет отличаться от начального.

Иногда с этим можно бороться, фиксируя/пересчитывая таблицу в памяти перед операцией (например, добавлением индекса).
Может, еще что-то вспомню
F1 творит чудеса
 
Максим Зеленский, большое спасибо!
 
Дополнение:
Сортировка только по одному столбцу не гарантирует сохранения предыдущего порядка сортировки по другим столбцам.
F1 творит чудеса
 
Максим Зеленский, спасибо за тему
Цитата
Максим Зеленский написал:
точно не гарантирует сохранение порядка строк:
глобальная группировка
удаление дубликатов
слияние/join/merge (практически любой вариант слияния)
Наверное надо упомянуть какие действия (ссылка) сохранят порядок строк, например, для удаления дубликатов достаточно, перед удалением дубликатов, обернуть таблицу в Table.Buffer. И пример
 
Цитата
Михаил Л написал:
достаточно, перед удалением дубликатов, обернуть таблицу в Table.Buffer
как я упоминал в той теме, придется писать "на текущий момент достаточно" :D хотя буфера, по идее, вечны :)
F1 творит чудеса
 
Цитата
Михаил Л написал:
сохранят порядок строк, например, для удаления дубликатов достаточно, перед удалением дубликатов, обернуть таблицу в Table.Buffer
Для кучи Гугл перевел как "случайный побочный эффект". Ужас
Код
Факт, что буферизация или добавление столбца индекса приводит к сохранению исходного порядка, является просто случайным побочным эффектом
 
Михаил Л, а чего он не так перевёл? Все ровно так как написал Эрен. Можно ещё косяк sort+distinct обозвать как collaterial damage. Или, говоря по-русски: Лес рубят - щепки летят.
Изменено: PooHkrd - 29 июл 2020 00:20:57
Вот горшок пустой, он предмет простой...
 
Недавно имел очень любопытную дискуссию с хорошим специалистом по PQ, в результате которой родилась следующая цепочка рассуждений и утверждений:
  1. Сами по себе функции типа Table.Distinct или List.Distinct не являются тем, кто меняет порядок строк в таблице/списке. Так, скорее всего, на статичных источниках данных (типа явных перечислений или явно заданных таблицах, или других) не удается подтвердить изменение порядка строк для этих функций.
  2. В основном всё упирается в то, включается ли стриминговая семантика для конкретного источника данных. Если да (источник с потенциально изменяемым порядком строк), то тогда, при выполнении функции, за счет стриминга в нее может подаваться переменный набор строк (т.е. в другом порядке, даже если количество строк не изменилось).
  3. Некоторые функции действительно могут менять порядок строк в таблице - это функции группировки и слияния (merge/join). Об этом, как правило, написано в документации, но да, для обычного пользователя (особенно родом из Excel) это вообще не очевидно.
  4. В любом случае хорошее правило:
    Если для каких-то целей важен порядок строк, его необходимо явно задать и загнать таблицу в буфер перед операцией, или обеспечить восстановление нужного порядка после операции.
  5. Это может быть слишком расточительно, но надежно.
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
удаление дубликатов списка (List.Distinct)
по подтверждению одного из разработчиков, также сохранение порядка не гарантировано (иногда может помочь List.Buffer, но зависит от источника данных, из которого этот список пришел)
F1 творит чудеса
 
А меня раздражает в PQ, что сбрасываются типы столбцов после некоторых операций, после чего нужно опять всё восстанавливать. Плюс не в Office 365 нет IntelliSense. Этот как в 80-е годы набирали код в командной строке.
There is no knowledge that is not power
 
Цитата
SuperCat написал:
Плюс не в Office 365 нет IntelliSense
Есть...
Версия PQ 64-разрядная версия 2.82.5858.241
Изменено: Максим Зеленский - 5 авг 2020 09:54:11
F1 творит чудеса
 
Цитата
SuperCat написал:
сбрасываются типы столбцов после некоторых операций
В основном слетают типы, когда вы например, разворачиваете вложенные таблицы.
Не так чтобы сильно давно, но уже давненько ввели сохранение типа столбцов при группировке с агрегацией "Все строки" - теперь типы прямо прописываются в коде и не слетают при разворачивании.
Если вы получили вложенную таблицу другими способами, то там тоже есть подходы. Например, прописать возвращаемый тип в функции, которая делает таблицу, и т.п.
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
Есть...
это ж как раз в О365. А Сверхкот как раз написал
Цитата
SuperCat написал:
не в Office 365
MS вообще забил на развитие PQ в чем-либо кроме О365 и PBI. С них кэшфлоу и толще и стабильнее.
Вот горшок пустой, он предмет простой...
 
Да, проглядел. Надстройка PQ уже давненько не обновлялась, отстает примерно на 20 релизов :) В 2016-2019 тоже отстает, не знаю, на сколько версий.
Но можно использовать Visual Studio Code, там есть полная поддержка Power Query - с интеллисенсом, даж со справкой - всё как внутри. Плюс поиск, массовая замена и всё как мы любим в Code
F1 творит чудеса
 
Самая проблемная, похоже, сортировка
Код
let
    Source = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"№", Int64.Type}, {"П1", type number}, {"П2", type number}}),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"№"}, "Attribute", "Value"),
    #"Added Custom" = Table.AddColumn(#"Unpivoted Other Columns", "Custom", each [Attribute] & "." & Text.From([#"№"])),
    #"Sorted Rows" = Table.Sort(#"Added Custom",{{"Value", Order.Descending}}),
    bufferedTable = Table.Buffer(#"Sorted Rows"),
    maxPartWithoutBuffer = Table.FirstN(#"Sorted Rows", Table.RowCount(Source)),
    maxPartWithBuffer = Table.FirstN(bufferedTable, Table.RowCount(Source)),
    withoutSortFirstN = Table.FirstN(#"Added Custom", Table.RowCount(Source)),
    // на буферезованной таблице без ошибки
    withBuffer = Table.FromRows({maxPartWithBuffer[Custom]}),
    // а без буфера - ошибка, тянутся не 8 строк, а все 16! :) 
    withoutBuffer = Table.FromRows({maxPartWithoutBuffer[Custom]}),
    // но если нет сортировки, то и буфер не нужен!
    withoutSortFirstNT = Table.FromRows({withoutSortFirstN[Custom]})
in
    withoutSortFirstNT

Уж сколько лет проблеме, а поезд всё ещё в огне. Надо найти ту проблемную с Table.NestedJoin
 
Цитата
Максим Зеленский написал:
по  подтверждению одного из разработчиков , также сохранение порядка не гарантировано
запутал я Эрена окончательно  :D :
Цитата
I'm not sure. You'll have to try it
F1 творит чудеса
 
Цитата
Андрей VG написал:
Надо найти ту проблемную с Table.NestedJoin
А чего её искать? Вот она.
Андрей ваш пример просто прекрасен. Я даже в растерянности от таких глюков.
Цитата
Максим Зеленский написал:
запутал я Эрена
После темы с Type time bug я уже этому не удивляюсь. Его вопросы тогда я так и не понял, хотя ему аж три русских человека английскими буквами все написали с табличками и примерами. Ладно, я коряво изъясняюсь, но у вас и второго нашего соотечественника явно скилл в ангельском заметно выше. А он пометил тему как решенную и был таков. Красавчег. Не знаю что там за помутнение на него напало, обычно вполне адекватный гражданин.
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
Я даже в растерянности от таких глюков.
Он лечибельный, но каждый раз после сортировки делать Table.AddIndexColumn
Код
#"Sorted Rows" = Table.AddIndexColumn(Table.Sort(#"Added Custom",{{"Value", Order.Descending}}), "id")
как-то бесчеловечно. А команда разработчиков, полагаю, и не собирается исправлять этот баг :(   Вполне возможно, из команды свалили математики, которые сформировали каркас оптимизатора (упростителя выражений).
Изменено: Андрей VG - 17 авг 2020 11:57:02
 
Андрей VG, про это в курсе, но опять же, как писал выше Максим, это работает только потому что: "так получилось". И гарантировать что такое будет работать и дальше никто не может.
Вот горшок пустой, он предмет простой...
 
Цитата
Андрей VG написал:
Самая проблемная, похоже, сортировка
любопытно, что
Код
withoutBuffer = Table.FromRows({maxPartWithoutBuffer[Custom]})
работает с ошибкой, а вот
Код
= Table.FromColumns({maxPartWithoutBuffer[Custom]})

и
Код
= Table.FromRows(List.Zip({maxPartWithoutBuffer[Custom]}))

без ошибки.
И да, при удалении сортировки, или размещении ее после шага maxPartWithoutBuffer (что не имеет смысла, конечно) - всё работает... Странный глюк. Очевидно, связан с сочетанием сортировки и Table.FirstN.
Заброшу команде разработки, посмотрим, что они скажут
F1 творит чудеса
 
Цитата
Андрей VG написал:
из команды свалили математики, которые сформировали каркас оптимизатора
х.з... я знаю трех разрабов PQ - Ehren von Lehe, Curt Hagenlocher, Matt Masson - все на месте. Еще Miguel Llopis, но он скорее PM, а не разраб. Но кто был там еще и оставался непубличным - х.з.
Курт как-то обмолвился, что "если бы делали сейчас - некоторые вещи делали бы по-другому", но это так, для истории :)
F1 творит чудеса
 
Ещё одно забавное поведение ИИ
Код
let
    Source = Table.FromColumns({{"one", "two"}}, {"name"}),
    trans1 = Table.TransformColumns(Source, {{"name", each _, Text.Type}}), // has not type text
    trans2 = Table.TransformColumns(Source, {{"name", each _ & "", Text.Type}}) // has type text
in
    trans2

Раз в trans1 мы ничего не делаем, то и тип столбцу присваивать не будем :)
Изменено: Андрей VG - 7 сен 2020 18:54:10
 
Андрей VG, не думаю, что только в этом дело :)
вот так работает, хотя мы ничего не делаем:
Код
= Table.TransformColumns(Source, {{"name", (_) as text=> _}})

Скорее всего (предполагаю на 80%) тип не присваивается только для each _
Но в любом случае, это не конвертация/проверка типа значений, а присвоение типа столбцу:
Код
= Table.TransformColumns(Source, {{"name", (_) as text=> _, type date}})
= Table.TransformColumns(Source, {{"name", each _ & "", type date}})
в обоих случаях даст тип столбца date, а в ячейках будет по-прежнему текст
Вообще присвоение и проверка типов та еще история. Надо минимум полбанки, чтобы разобраться
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
Но в любом случае, это не конвертация/проверка типа значений, а присвоение типа столбцу:
так вот этого и не происходит. Большое спасибо за ссылку!
 
Еще вот любопытное наблюдение:
Код
let
    Source = Table.FromRows({{"01.01.2020"}}, {"date1"}),
    Typed = Table.TransformColumnTypes(Source,{{"date1", type date}}),
    Added2Typed = Table.AddColumn(Typed, "date2", each [date1], type date),
    ColumnsOfType = Table.ColumnsOfType(Added2Typed, {type date})
in
    ColumnsOfType

не подглядывая, какие имена столбцов будут в списке? :)
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
какие имена столбцов будут в списке?
по идее, оба два: date1, date2
 
Андрей VG, По идее да, но нет, будет только второй. Вопрос на засыпку: какого типа первый столбец? :)
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
какого типа первый столбец?
По подсказке Date.Type, а вот что крутит Table.TransformColumnsType весьма забавно. Если вернуть
Код
let
    Source = Table.FromRows({{"01.01.2020"}}, type table [date1 = Date.Type]),
    //Typed = Table.TransformColumnTypes(Source,{{"date1", type date}}),
    Added2Typed = Table.AddColumn(Source, "date2", each [date1] + #duration(1, 0, 0, 0), type date),
    ColumnsOfType = Table.ColumnsOfType(Added2Typed, {Date.Type})
in
    ColumnsOfType
Typed, то даже в такой конструкции возвращается только date2. Хотя сводка по типам столбцов таблицы говорит, что Date.Type
Код
let
    Source = Table.FromRows({{"01.01.2020"}}, type table [date1 = Date.Type]),
    Typed = Table.TransformColumnTypes(Source,{{"date1", type date}}),
    Added2Typed = Table.AddColumn(Typed, "date2", each [date1] + #duration(1, 0, 0, 0), type date),
    tableInfo = Table.Schema(Added2Typed)
in
    tableInfo
Косяки-с :)
 
нет, не косяки, а типичное буквоедство :):)
На самом деле настолько неочевидный момент, что только кропотливое изучение схемы дает ответ.
В Typed тип nullable date, а в Added2Typed - просто date. И пойди догадайся.
Причина в том, что Table.TransformColumnTypes всегда присваивает nullable type.
Пытался сделать такую операцию:
Код
=Table.ReplaceValue(Source, "", null, Replacer.ReplaceValue, Table.ColumnsOfType(Source, {type text}))

Если все столбцы были типизированы через Table.TransformColumnTypes, замену не делало совсем, и Table.ColumnsOfType давало пустой список.
Потом обнаружил, что замену делает только в тех столбцах, где тип был задан по примеру Added2Typed (через присвоение типа в процессе создания столбца, например, или через прописывание типа таблицы).
Вот такая конструкция зато работает
Код
=Table.ReplaceValue(Source, "", null, Replacer.ReplaceValue, Table.ColumnsOfType(Source, {type nullable text}))

пришлось долго гуглить и спрашивать старших товарищей. В общем, если кратко, то любой примитивный тип конформится с им же nullable, НО не наоборот:
Код
= Type.Is(type nullable date, type date) // false
= Type.Is(type date, type nullable date) // true

У Бена это тоже расписано, хоть и не просто
F1 творит чудеса
 
Цитата
Максим Зеленский написал:
В Typed тип nullable date, а в Added2Typed - просто date
Да, соглашусь, года три-четыре тому назад Power Query трепетно относился к этому моменту. Потом похоже убрали, чтобы не раздражать пользователей. Но, вместо того, чтобы привести типизацию к единому виду, понаделали костылей. :)
Страницы: 1
Читают тему (гостей: 1)
Наверх