Разделите данные в тексте с различными образцами

Я пытаюсь сопоставить набор данных с ключевым словом с текстом в другом наборе данных.

S.No    Keyword
1       DKB105A
2       DLB01SA
3       B107A0
4       LB104A0
5       KA02SA
6       A02SA

ID     Date       Text
1   2/11/2020   wrong_B107A0/act
2   2/12/2020   gra/A02SA_fin
3   2/13/2020   Acc/DKB105A/acnt
4   2/14/2020   DLB01SA
5   2/15/2020   KA02SA_attr_to
6   2/16/2020   

и ожидаемый результат

ID  Date             Text           Keyword
1   2/11/2020   wrong_B107A0/act    B107A0
2   2/12/2020   gra/A02SA_fin       A02SA
3   2/13/2020   Acc/DKB105A/acnt    DKB105A
4   2/14/2020   DLB01SA             DLB01SA
5   2/15/2020   KA02SA_attr_to      KA02SA
6   2/16/2020       

Сначала я попытался отделить текст, как показано ниже, а затем попытался сопоставить ключевое слово.

splitdata= setDT(data)[,tstrsplit(Text, '/')]

Однако позже я понял, что в тексте есть разные шаблоны, которые я не могу разделить с помощью одного шаблона. Есть ли способ, которым я могу сравнить ключевые слова в наборе данных1 с текстом в наборе данных2.

Всего 3 ответа


Это должно быть то, что вам нужно:

library(data.table)
keys <- fread('S.No    Keyword
1       DKB105A
2       DLB01SA
3       B107A0
4       LB104A0
5       KA02SA
6       A02SA')

dt <- fread('ID     Date       Text
1   2/11/2020   wrong_B107A0/act
2   2/12/2020   gra/A02SA_fin
3   2/13/2020   Acc/DKB105A/acnt
4   2/14/2020   DLB01SA
5   2/15/2020   KA02SA_attr_to
6   2/16/2020   _')

keywrds <- paste(keys$Keyword,collapse = '|')
library(stringi)
dt[,Keyword:=unlist(stri_extract_all(Text,regex = keywrds))]
dt
#>    ID      Date             Text Keyword
#> 1:  1 2/11/2020 wrong_B107A0/act  B107A0
#> 2:  2 2/12/2020    gra/A02SA_fin   A02SA
#> 3:  3 2/13/2020 Acc/DKB105A/acnt DKB105A
#> 4:  4 2/14/2020          DLB01SA DLB01SA
#> 5:  5 2/15/2020   KA02SA_attr_to  KA02SA
#> 6:  6 2/16/2020                _    <NA>

Создано 2020-02-11 пакетом представлением (v0.3.0)


Вы можете сделать это в базе R с помощью sapply следующим образом:

dt$Keyword <- sapply(dt$Text, function(txt) {

    keys$Keyword[sapply(keys$Keyword, function(i) { grepl(i, txt) })]

})

Обратите внимание, что при этом возвращается столбец списка, в котором каждая позиция в этом списке является вектором совпадающих ключевых слов - или, если совпадений нет, вектором длины 0. Поэтому, если в dt$Text[i] есть более одного ключевого слова dt$Text[i] --- как и в случае с одной из ваших строк --- список в dt$Keyword[i] будет включать их все. Если вы знаете, что ваши строки никогда не будут содержать более одного ключевого слова и хотите вернуть векторный столбец вместо столбца списка, вы можете просто обернуть все это в unlist() . Итак, результат в вашем случае с использованием таблиц данных, опубликованных в другом ответе:

    > dt
   ID      Date             Text      Keyword
1:  1 2/11/2020 wrong_B107A0/act       B107A0
2:  2 2/12/2020    gra/A02SA_fin        A02SA
3:  3 2/13/2020 Acc/DKB105A/acnt      DKB105A
4:  4 2/14/2020          DLB01SA      DLB01SA
5:  5 2/15/2020   KA02SA_attr_to KA02SA,A02SA
6:  6 2/16/2020                _             

fuzzyjoin решение fuzzyjoin , использующее regex_join

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

образец данных

library( data.table)
library( fuzzyjoin )

dt1 <- fread('S.No    Keyword
1       DKB105A
2       DLB01SA
3       B107A0
4       LB104A0
5       KA02SA
6       A02SA')

dt2 <- fread('ID     Date       Text
1   2/11/2020   wrong_B107A0/act
2   2/12/2020   gra/A02SA_fin
3   2/13/2020   Acc/DKB105A/acnt
4   2/14/2020   DLB01SA
5   2/15/2020   KA02SA_attr_to
6   2/16/2020   ""')

код

fuzzyjoin::regex_left_join( dt2, dt1, by = c( Text = "Keyword"))

выход

#    ID      Date             Text S.No Keyword
# 1:  1 2/11/2020 wrong_B107A0/act    3  B107A0
# 2:  2 2/12/2020    gra/A02SA_fin    6   A02SA
# 3:  3 2/13/2020 Acc/DKB105A/acnt    1 DKB105A
# 4:  4 2/14/2020          DLB01SA    2 DLB01SA
# 5:  5 2/15/2020   KA02SA_attr_to    5  KA02SA
# 6:  5 2/15/2020   KA02SA_attr_to    6   A02SA
# 7:  6 2/16/2020                    NA    <NA>

Обновить

с силой регулярных выражений развязал ...

fuzzyjoin::regex_left_join( dt2, copy(dt1)[, regex := paste0("[^a-zA-Z]", Keyword, "|^", Keyword)], 
                            by = c( Text = "regex"))[, -"regex"]

#    ID      Date             Text S.No Keyword
# 1:  1 2/11/2020 wrong_B107A0/act    3  B107A0
# 2:  2 2/12/2020    gra/A02SA_fin    6   A02SA
# 3:  3 2/13/2020 Acc/DKB105A/acnt    1 DKB105A
# 4:  4 2/14/2020          DLB01SA    2 DLB01SA
# 5:  5 2/15/2020   KA02SA_attr_to    5  KA02SA
# 6:  6 2/16/2020                    NA    <NA>

Есть идеи?

10000