Страницы: 1
RSS
Power Query. Разделение текста пробелом по условию, необходимо разделить слова по условию, где соединяются строчная и прописная буквы и др.: "аА", "а)А"
 
Здравствуйте!
Помогите пожалуйста разобраться с написанием запроса в Power Query, где можно текст "РеспубликаАдыгея(Адыгея)" преобразовать так: "Республика Адыгея (Адыгея)".
Кабардино-БалкарскаяРеспублика to Кабардино-Балкарская Республика.

Если не сложно, то прошу дать ссылку или прокомментировать как собирается формула в PQ.
P.S.: при открытии файла подходит Юникод-(UTF 8).

Благодарю!  
 
Как-то так:
Код
let
    fnCamelCases = (Source)=> //by Sergey Lossev https://datachant.com/2018/02/14/split-camelcase-headers-m/
    let
        to_list = Text.ToList(Source),
        to_table = Table.FromList(to_list, (x)=>{x, Text.Lower(x)=x}, {"word", "isLower"}),
        group_chars = Table.Group(to_table, {"isLower"}, {{"word", each Text.Combine([word])}}, 0, (a,b)=>if b[isLower] then 0 else 1),
        len = Table.AddColumn(group_chars, "len", each Text.Length([word])),
        group_words = Table.Group(len, {"len"}, {{"word", each Text.Combine([word])}}, 0, (a,b)=>if (a[len]=1 and b[len]=1) then 0 else 1),
        combine = Text.Combine(group_words[word], " ")
    in
        combine,
    Source = Csv.Document(Web.Contents("https://www.planetaexcel.ru/bitrix/components/bitrix/forum.interface/show_file.php?fid=367107&action=download"),[Delimiter=","]),
    PromotedHeaders = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    ChangedType = Table.TransformColumnTypes(PromotedHeaders,{{"subject", type text}, {"t1", type text}, {"fond", type text}, {"salary", type text}, {"monthyear", type date}, {"year", Int64.Type}}),
    Camel = Table.TransformColumns(ChangedType, {{"subject", each fnCamelCases( _ ), type text}}),
    ReplacedValue = Table.ReplaceValue(Camel,"( "," (",Replacer.ReplaceText,{"subject"}),
    ReplacedValue1 = Table.ReplaceValue(ReplacedValue,"- ","-",Replacer.ReplaceText,{"subject"}),
    ReplacedValue2 = Table.ReplaceValue(ReplacedValue1,"— ","—",Replacer.ReplaceText,{"subject"}),
    ReplacedValue3 = Table.ReplaceValue(ReplacedValue2,"край"," край",Replacer.ReplaceText,{"subject"}),
    ReplacedValue4 = Table.ReplaceValue(ReplacedValue3,"область"," область",Replacer.ReplaceText,{"subject"}),
    ReplacedValue5 = Table.ReplaceValue(ReplacedValue4,"автоном"," автоном",Replacer.ReplaceText,{"subject"}),
    ReplacedValue6 = Table.ReplaceValue(ReplacedValue5,"округ"," округ",Replacer.ReplaceText,{"subject"})
in
    ReplacedValue6
Изменено: PooHkrd - 14.11.2019 17:20:07
Вот горшок пустой, он предмет простой...
 
еще  вариант
Код
let
    Source = Csv.Document(Web.Contents("https://www.planetaexcel.ru/bitrix/components/bitrix/forum.interface/show_file.php?fid=367107&action=download"),null,null,null,65001),
    Replaced = Table.ReplaceValue(Table.PromoteHeaders(Source, [PromoteAllScalars=true]),null,null,
            (a,b,c)=> let 
                num       = Number.From(Text.Replace(a,".",",")), 
                chars     = {"А".."Я"}&{"Ё","(",")"}, 
                words     = {"край","область","автономн","округ"}, 
                positions = {0}&Text.PositionOfAny(a, chars, 3)&List.Combine(List.Transform(words,each Text.PositionOf(a,_,3))),
                splitter  = Splitter.SplitTextByPositions(List.Sort(positions)), 
                replaced  = List.Accumulate({"- ","( "," )"},Text.Combine(splitter(a)," "),(d,e)=>Text.Replace(d,e,Text.Trim(e)))
            in 
                if a="NULL" then null else try num otherwise Text.Trim(replaced)
        ,{"subject","t1","fond","salary"}),
    Typed = Table.TransformColumnTypes(Replaced,{{"subject", type text}, {"t1", type number}, {"fond", type number}, {"salary", type number}, {"monthyear", type date}, {"year", Int64.Type}})
in
    Typed
 
Доброе время суток.
Тёзка, а почему не на регулярках? Размножил исходный файл до 900000 строк получилось почти в четыре раза быстрее ;)
Код
let
    toJsString = (string) => Text.Replace(Text.Replace(Text.Replace(Text.Replace(Text.Replace(Text.Replace(Text.Replace(string, "\", "\\"), "&", "\&"), "'", "\'"), """", "\"""), "#(cr)", "\r"), "#(lf)", "\n"), "#(tab)", "\t"),
    jsReg = (string) => Web.Page("<script>var r =/([а-яё])(?=[А-ЯЁ]|\()/g;var t='" & string & "';document.write(t.replace(r,'$1 '));</script>")[Data]{0}[Children]{0}[Children]{1}[Text]{0},
    Source = Csv.Document(File.Contents("C:\path\data.csv"),[Delimiter=",", Columns=6, Encoding=65001, QuoteStyle=QuoteStyle.None]),
    setHead = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    cols = Table.ToColumns(setHead),
    maker = Text.Split(jsReg(toJsString(Text.Combine(cols{0}, "|"))), "|"),
    test = {maker} & List.Range(cols, 1),
    result = Table.FromColumns(test, Table.ColumnNames(setHead))
in
    result
Изменено: Андрей VG - 14.11.2019 22:28:35
 
Андрей VG, я правильно понимаю, что вот это Text.Combine(cols{0}, "|") нужно чтобы инициализировать regexp только один раз и за раз прогнать весь столбец. А если вызывать эту функцию для каждого значения столбца отдельно то будет сильно медленнее?
И есть ли ограничение на длину строки, которую можно обработать таким образом?
Кстати, а вы не пробовали скармливать в регулярку только список уникальных, а результат потом джойнить к исходным данным? Может так будет еще быстрее?
З.Ы. попробовал ваш вариант. Я уж развесил губу что ваш шаблон и края с областями перелопатит  8) , а их все равно надо заменять вручную. Но все равно очередное огромное спасибо за примеры с регулярками. Как припрет, хоть будет источник знаний куда припасть. А то ссылка на CamelCases висела у меня года полтора, как вы мне её скинули, и вот в первый раз пригодилась!  :D
Изменено: PooHkrd - 15.11.2019 09:48:39
Вот горшок пустой, он предмет простой...
 
Привет, Алексей
Цитата
PooHkrd написал:
Я уж развесил губу что ваш шаблон и края с областями перелопатит
Я делал строго по постановке задачи
Цитата
ivanka написал:
де можно текст "РеспубликаАдыгея(Адыгея)" преобразовать так: "Республика Адыгея (Адыгея)".Кабардино-БалкарскаяРеспублика to Кабардино-Балкарская Республика.
Если ТС лень заниматься анализом что где не так, то не считаю, что я должен хоть как-то этим заниматься. Кому нужно, тот и анализирует свои данные. Сугубо для вас просто дополняем регулярку
Код
/([а-яё])(?=[А-ЯЁ]|\(|автоном|округ|область|край)/g

Цитата
PooHkrd написал:
И есть ли ограничение на длину строки, которую можно обработать таким образом?
По идее, длина строки не менее чем 2^31 символов.
Цитата
PooHkrd написал:
Кстати, а вы не пробовали скармливать в регулярку только список уникальных, а результат потом джойнить к исходным данным? Может так будет еще быстрее?
Нет, не пробовал, может вечером протестирую. По идее должно быть быстрее.
Цитата
PooHkrd написал:
А если вызывать эту функцию для каждого значения столбца отдельно то будет сильно медленнее?
Наверняка да, вызов для каждого элемента списка Web.Page() не самое дешёвое удовольствие. Но можете протестировать :)
Updated.
Не утерпел с Join на уникальных - в два раза быстрее.
Код
let
    toJsString = (string) => Text.Replace(Text.Replace(Text.Replace(Text.Replace(Text.Replace(Text.Replace(Text.Replace(string, "\", "\\"), "&", "\&"), "'", "\'"), """", "\"""), "#(cr)", "\r"), "#(lf)", "\n"), "#(tab)", "\t"),
    jsReg = (string) => Web.Page("<script>var r =/([а-яё])(?=[А-ЯЁ]|\(|автоном|округ|область|край)/g;var t='" & string & "';document.write(t.replace(r,'$1 '));</script>")[Data]{0}[Children]{0}[Children]{1}[Text]{0},
    Source = Csv.Document(File.Contents("C:\path\data.csv"),[Delimiter=",", Columns=6, Encoding=65001, QuoteStyle=QuoteStyle.None]),
    setHead = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    uniques = List.Distinct(setHead[subject]),
    replaced = Text.Split(jsReg(toJsString(Text.Combine(uniques, "|"))), "|"),
    pairs = Table.FromRows(List.Zip({uniques, replaced}), {"link", "Требуемое"}),
    result = Table.Join(setHead, {"subject"}, pairs, {"link"}),
    #"Removed Columns" = Table.RemoveColumns(result,{"subject", "link"}),
    #"Reordered Columns" = Table.ReorderColumns(#"Removed Columns",{"Требуемое", "t1", "fond", "salary", "monthyear", "year"}),
    #"Renamed Columns" = Table.RenameColumns(#"Reordered Columns",{{"Требуемое", "subject"}})
in
    #"Renamed Columns"

На рабочей машине 994000 строк загрузилось за 11 секунд (автоподбор ширины столбца отключен).
Изменено: Андрей VG - 15.11.2019 10:45:31
 
Цитата
Андрей VG написал:
Сугубо для вас просто дополняем регулярку
Огонь! Спасибо. Блин где бы взять время еще и на изучения этой темы, когда по работе оно на фиг не нужно. :D
Заделал стендик для погонялок. И сам погонял.
Вот машинка.

Вот результаты запросов из стенда. Время в секундах. Разброс аховый, но в принципе все работает довольно быстро.

Grouped это я оптимизировал свой запрос и Андрея VG , т.е. передачей в обработку значения группируются, а потом вся остальная таблица восстанавливается.
В запрос Андрея Лящук извините не лез, раз он так пишет, пусть сам и правит.  :D
Вот горшок пустой, он предмет простой...
 
Алексей, спасибо!
 
Андрей VG, кстати, заметил, что при работе функции от Сергея Лоссева проц загружен на 100% все 4 потока, а вот регулярки вообще его не напрягают. Почему так - ХЗ.
Вот горшок пустой, он предмет простой...
Страницы: 1
Наверх