Страницы: 1
RSS
Power Query. Настройка фильтрации по ключевым словам - Table.SelectRows.
 
Пытаюсь отфильтровать в таблице столбец с текстом. Пробовал по разному, вот последний вариант, но он не верный.

Код
Table.SelectRows(#"Измененный тип", each Text.Contains(Text.Lower([Текст]), "ключ1") or Text.Contains(Text.Lower([Текст]), "ключ2")
 and Text.Contains(Text.Lower([Текст]), "ключ3") or Text.Contains(Text.Lower([Текст]), "ключ4") or Text.Contains(Text.Lower([Текст]), "ключ5")
 and not Text.Contains(Text.Lower([Текст]), "ключ6") or Text.Contains(Text.Lower([Текст]), "ключ7"))

Что хочу получить.  Должны остаться строки  обязательно содержащие ключ1 или ключ2.  И из них  только строки с вхождением ключь3 или ключ4 или ключ5. Но если текст содержит ключ6 или ключ 7 то эти строки должны быть удалены.

Как делаю. В Excel составил табличку которая набирает текст формулы по ключам с  минус-словам. Ее импортирую в PQ запросом, копирую руками и вставляю в код. Неудобно что для этого нужно заходить и выходить из PQ. Можно ли как то сделать, чтобы запрос сам забирал и подставлял ключи в код из этого запроса? Как бы вы поступали в таких случаях. Может есть другие варианты.

С синтаксисом сам не смог разобраться. С английским вообще плохо, а машинный перевод не всегда понятен. Когда простая фильтрация более менее получается, а вот кода посложней и нужно использовать много операторов и, или, если еще и с разными столбцами то беда.
Еще вопрос по теме. В ячейке иногда по несколько тысяч символов. Но показывает он чуть более 1000, в строке формул также не весь текст. Причем в видимой части ключа в нем нет. Но я проверял, что фильтрует верно так как в исходном тексте ключ присутствует. Мне интересно он весь текст "просматривает" или есть ограничения, как в Excel?
 
Цитата
Shima написал:
или есть ограничения, как в Excel?
https://support.office.com/ru-ru/article/%D0%A1%D0%BF%D0%B5%D1%86%D0%B8%D1%84%D0%B8%D0%BA%­D0%B0%D1%8...
Цитата
Shima написал:
Может есть другие варианты.
есть, конечно, но лучше приложить хотя бы простой пример.
Цитата
Shima написал:
Text.Contains(Text.Lower([Текст]), "ключ1")
а ключ1 всегда в нижнем регистре? можно сравнивать без учета регистра, вот так:
Код
Text.Contains([Текст], "ключ1", Comparer.OrdinalIgnoreCase)

Кроме того, вы можете использовать скобки в формуле для обозначения логики. например так (много строк необязательно, для наглядности),
Код
(
    (text = key1) or 
    (text = key2)
) and 
(
    (
        (text = key3) or 
        (text = key4) or 
        (text = key5)
    ) and 
    not (
    (text = key6) or 
    (text = key7)
    )
)
F1 творит чудеса
 
Добрый вечер.
Цитата
но лучше приложить хотя бы простой пример
Есть, но там особо смотреть не на что(рис для условного солбца). Пока она выглядит вот как на рис. Передаю в PQ табличку E10:E11. Но я вот как раз сейчас продумываю, как мне удобней сделать. Завтра смогу дать файлом с учетом ваших поправок.
Цитата
а ключ1 всегда в нижнем регистре?
Наверное да. Текст может быть написан и капсом и вперемежку. Я поэтому и перевожу все в нижний регистр.

Код

Table.SelectRows(#"Измененный тип", each Text.Contains([Текст], (
    (text = key1) or 
    (text = key2)
) and 
(
    (
        (text = key3) or 
        (text = key4) or 
        (text = key5)
    ) and 
    not (
    (text = key6) or 
    (text = key7)
    )
), Comparer.OrdinalIgnoreCase))


Правильно понял, вот так должен выглядеть мой вариант? Вот я сегодня с этим и помучился. Понимаю, что как то должно быть по другому, как только скобки не ставил.
Изменено: Shima - 13.09.2017 16:45:33
 
что-то вы намудрили. Вы писали:
Цитата
Shima написал:
Что хочу получить.  Должны остаться строки  обязательно содержащие ключ1 или ключ2.  И из них  только строки с вхождением ключь3 или ключ4 или ключ5. Но если текст содержит ключ6 или ключ 7 то эти строки должны быть удалены.
сделайте функцию проверки на нахождение ключа из заданного списка в тексте, которая берет список ключей, текст, проверяет, если хоть один из ключей есть в тексте - то TRUE. Она очень простая, в 1 строку можно:
Код
// fnCompareGroups
(keys as list, text as text) as logical =>
let
    Source = List.AnyTrue(List.Transform(keys, (key)=>Text.Contains(text, key, Comparer.OrdinalIgnoreCase)))
in
    Source

дальше создаете нужные списки (группы) ключей и проверяйте вот таким образом:
Код
= Table.SelectRows(Таблица, each fnCompareGroups(Ключи1, [Текст]) and fnCompareGroups(Ключи2, [Текст]) and not fnCompareGroups(КлючиМинус, [Текст]))

Как видите, проверяем, есть ли в тексте хоть один ключ из первого списка И хоть один из второго И НЕ ключ из третьего.
Подробнее в файле
F1 творит чудеса
 
Максим Зеленский, спасибо большое. Настроил, все работает с формулой fnCompareGroups. Буду с ней теперь пробовать. Удобно, что не нужно заходить в PQ, изменил ключи и сразу в сводке видно. А у меня как раз много фильтраций по тексту.
Цитата

Кроме того, вы можете использовать скобки в формуле для обозначения логики. например так (много строк необязательно, для наглядности)
А вот с этим, так и не разобрался, поэтому код у меня громоздкий и не читабельный получается.

Цитата
Должны остаться строки  обязательно содержащие ключ1 или ключ2.  И из них  только строки с вхождением ключь3 или ключ4 или ключ5. Но если текст содержит ключ6 или ключ 7 то эти строки должны быть удалены.
Если это про прикрепленную мною картинку, то она не целиком относится к сказанному. Я сначала фильтрую вообще весь текст, чтобы остался только одной тематики. А потом при помощи этой формулы создаю дополнительные условные столбцы. Ну например, если есть это и это слово то поле - Название1, если есть другие ключи, то поле Название2 и тд.
 
Добрый день.
Как правильно написать код используя функцию  - fnCompareGroups? Добавляю условный столбец при условии, что текст в нескольких столбцах содержит один и тот же ключ1.
Написал так, вроде работает.
Код
AddПризнак = Table.AddColumn(Types, "Признак",
   each if fnCompareGroups({"ключ1"}, [Column1]) 
   or fnCompareGroups({"ключ1"}, [Column2]) 
   or fnCompareGroups({"ключ1"}, [Column3])
   then "Признак1" else ""),

Но теперь мне нужно добавить еще одно условие на присутствие в тексте ключ2 и присвоить  Признак2. Как то все очень громоздко получается. А как пользоваться скобками "(), [], {}" для сокращения кода не могу разобраться. Помогите поправить код и если не затруднит киньте ссылку, где про это все рассказано.
 
Код
AddПризнак = Table.AddColumn(Types, "Признак",
   each if fnCompareGroups({"ключ2"}, [Column1]) 
        then "Признак2" 
        else if [SIZE=14pt][B][COLOR=#FF0000]([/COLOR][/B][/SIZE]fnCompareGroups({"ключ1"}, [Column1]) 
                or fnCompareGroups({"ключ1"}, [Column2]) 
                or fnCompareGroups({"ключ1"}, [Column3])[SIZE=14pt][B][COLOR=#FF0000])[/COLOR][/B][/SIZE]
            then "Признак1" 
            else ""),

В общем, пользуйтесь логикой. выше логика такая:
если ключ2,
то Признак2,
иначе если (ключ1 в Столбец1 или в Столбец2 или в Столбец3),
   то Признак1,
   иначе ""
Цитата
Shima написал:
А как пользоваться скобками "(), [], {}" для сокращения кода не могу разобраться.
обычные круглые скобки в рамках if then else используются по математическим правилам, то есть логическое выражение внутри скобок вычисляется совместно.

фигурные и квадратные скобки служат совсем не для этого. Буквально, фигурные скобки - обозначение списка (list), квадратные - записи (record)
F1 творит чудеса
Страницы: 1
Наверх