R найти и заменить частичную строку на основе таблицы поиска - PullRequest
0 голосов
/ 08 июня 2018

Я нашел варианты по этой проблеме, но не могу предложить предложенные решения, работающие в моей ситуации.Я довольно новичок в R без какого-либо опыта программирования, так что, возможно, я просто упускаю что-то простое.Спасибо за любую помощь !!

У меня есть таблица данных со столбцом названий организаций, назовите ее Orgs $ OrgName.Иногда в строках есть орфографические ошибки, составляющие названия организации.У меня есть справочная таблица (импортированная из csv с общими орфографическими ошибками в одном столбце (орфография $ misspelt) и их исправления в другом столбце (орфография $ правильное).

Я хочу найти любые части строк OrgName, которыесопоставьте написание $ misspelt и замените только эти части на правильное написание $ правильное.

Я пробовал различные решения на основе mgsub, stri_replace_all_fixed, str_replace_all ( замена слов в строках была моей основной ссылкой)Но ничего не помогло, и все примеры, похоже, основаны на векторах, созданных вручную, используя vect1 <- c ("item1", "item2", item3 "), а не на поисковой таблице. </p>

Примермои данные:

                                         OrgName
1:                         WAIROA DISTRICT COUNCIL
2:                         MANUTAI MARAE COMMITTEE
3:                                C S AUTOTECH LTD
4:                  NEW ZEALAND INSTITUTE OF SPORT
5:                                 BRAUHAUS FRINGS
6:   CHRISTCHURCH YOUNG MENS CHRISTIAN ASSOCIATION

Таблица поиска:

    mispelt         correct 
1 ABANDONNED       ABANDONED            
2  ABERATION      ABERRATION            
3  ABILITYES       ABILITIES            
4   ABILTIES       ABILITIES            
5     ABILTY         ABILITY            
6    ABONDON         ABANDON

(В первых нескольких строках имен организаций нет орфографических ошибок, нов наборе данных еще 57000+)

ОБНОВЛЕНИЕ: Вот то, что я попробовал, основываясь на обновлении второго ответа (пробуя это сначала, поскольку это проще).d, но, надеюсь, кто-нибудь увидит, в чем дело?

library("stringi")
Orgs <- data.frame(OrgNameClean$OrgNameClean)
head(Orgs)
head(OrgNameClean)

write.csv(spelling$mispelt,file = "wrong.csv")
write.csv(spelling$correctspelling,file = "corrected.csv")

patterns <- readLines("wrong.csv")
replacements <- readLines("corrected.csv")
head(patterns)
head(replacements)

for(i in 1:nrow(Orgs)) {
  row <- Orgs[i,]
  print(as.character(row))
  #print(stri_replace_all_fixed(row, patterns, replacements, 
vectorize_all=FALSE))
  row <- stri_replace_all_regex(as.character(row), "\\b" %s+% patterns %s+% 
"\\b", replacements, vectorize_all=FALSE)
  print(row)
  Orgs[i,] <- row
}

head(Orgs)
Orgsdt <- data.table(Orgs)
head(Orgsdt)
chckspellchk <- Orgsdt[OrgNameClean.OrgNameClean %like% "ENVIORNMENT",,] 
##should return no rows if spelling correction worked
head(chckspellchk)

#OrgNameClean.OrgNameClean
#1:   SMART ENVIORNMENTAL LTD

ОБНОВЛЕНИЕ 2: больше информации - в поиске орфографии есть пробелы, если это имеет значение:

> head(spelling[mispelt %like% " ",,])
     mispelt correctspelling 
1: COCA COLA            COCA            
2:   TORTISE        TORTOISE      

> head(spelling[correctspelling %like% " "])
    mispelt correctspelling  
1:   ABOUTA         ABOUT A             
2:  ABOUTIT        ABOUT IT             
3: ABOUTTHE       ABOUT THE             
4:     ALOT           A LOT       
5: ANYOTHER       ANY OTHER             
6:    ASFAR          AS FAR 

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Мы можем использовать stringi stri_replace_*_all(), чтобы выполнить несколько замен для всей строки.

library("stringi")
string <- "WAIROA ABANDONNED COUNCIL','C S AUTOTECH LTD', 'NEW ZEALAND INSTITUTE OF ABERATION ABILITYES"
mistake <- c('ABANDONNED', 'ABERATION', 'ABILITYES', 'NEW')
corrected <- c('ABANDONED', 'ABERRATION', 'ABILITIES', 'OLD')

stri_replace_all_fixed(string, patterns, replacements, vectorize_all=FALSE)    
stri_replace_all_regex(string, "\\b" %s+% patterns %s+% "\\b", replacements, vectorize_all=FALSE)

Вывод:

[1] "WAIROA ABANDONED COUNCIL','C S AUTOTECH SGM', 'OLD ZEALAND INSTITUTE OF ABERRATION ABILITIES"

Некоторые примечания:

  • stri_replace_all_fixed заменяет вхождения совпадений с фиксированным шаблоном.

  • stri_replace_all_regex вместо этого использует шаблон регулярного выражения.Это позволяет нам определять границы слов: \b, чтобы избежать совпадений подстрок (альтернативой \bword\b является (?<=\W)word(?=\W)).

  • vectorize_all устанавливается в FALSE, в противном случае каждыйзамена применяется к новой копии оригинального предложения.Подробнее здесь .

Полный образец:

library("stringi")
Orgs <- data.frame("OrgName" = c('WAIROA ABANDONNED COUNCIL', 
                                 ' SMART ENVIORNMENTAL LTD',
                                 'NEW ZEALAND INSTITUTE OF ABERATION ABILITYES'),
                   stringsAsFactors = FALSE)

patterns <- readLines("wrong.csv")
replacements <- readLines("corrected.csv")

for(i in 1:nrow(Orgs)) {
  row <- Orgs[i,]
  print(as.character(row))
  row <- stri_replace_all_fixed(row, patterns, replacements, vectorize_all=FALSE)
  #row <- stri_replace_all_regex(as.character(row), "\\b" %s+% patterns %s+% "\\b", replacements, vectorize_all=FALSE)
  print(row)
  Orgs[i,] <- row
}

PS: я сделал отдельный CSV с одним столбцом без заголовка для каждогосимвольный вектор.Но есть много других способов прочитать CSV с помощью R и преобразовать столбцы в символьный вектор.

PS2: если вы хотите совпадения подстрок, например.совпадение ENVIORNMENT в ENVIORNMENTAL не используйте stri_replace_all_regex() вместе с границами слова \b. Этот является отличным учебником для улучшения ваших навыков регулярных выражений.

0 голосов
/ 08 июня 2018

Этот ответ потенциально слишком сложен для начинающего программиста, и я, возможно, пишу его больше как Python, а не как R (я немного заржавел над последним) * но у меня есть предложенное решение для вашей проблемы, которое неКстати, нетривиально.Проблемы, с которыми я столкнулся при рассмотрении других решений, которые вы рассматривали, заключаются в том, что они по отдельности затрагивают только одну небольшую часть большой головоломки, а именно то, что вы должны иметь возможность проверять каждое слово внутри каждой строки на соответствие вашему поиску.Таблица.Самый простой способ сделать это - написать несколько небольших функций, которые будут делать то, что вам нужно, а затем использовать семейство R применять функции для циклического просмотра записей и использования функций.

Единственная хитрость здесь заключается в использовании R environment в качестве таблицы поиска.По какой-то причине в R люди, кажется, мало говорят или действительно используют хеш-таблицы (настоящее имя для таблицы поиска), но они очень распространены в других языках.К счастью, R environments на самом деле являются просто реализацией хеш-таблицы C, что хорошо, потому что хеши очень быстрые и позволяют вам напрямую отображать одно значение в другое.( Подробнее об этом здесь , если интересно.)

* Я приветствую комментарии или правки других людей, которые сделали бы мой ответ более простым или более R-идиоматическим

# Some example data - note stringsAsFactors=FALSE is critical for this to work
Orgs <- data.frame("OrgName" = c('WAIROA ABANDONNED COUNCIL', 
                                 'C S AUTOTECH LTD', 
                                 'NEW ZEALAND INSTITUTE OF ABERATION ABILITYES'),
                   stringsAsFactors = FALSE)

spelling_df <- data.frame("Mistake" = c('ABANDONNED', 'ABERATION', 'ABILITYES', 'NEW'),
                          "Correct"= c('ABANDONED', 'ABERRATION', 'ABILITIES', 'OLD'),
                       stringsAsFactors = FALSE)


# Function to convert your data frame to a hash table
create_hash <- function(in_df){
  hash_table <- new.env(hash=TRUE)
  for(i in seq(nrow(in_df)))
  {
    hash_table[[in_df[i, 1]]] <- in_df[i, 2]
  }
  return(hash_table)
}

# Make the hash table out of your data frame
spelling_hash <- create_hash(spelling_df)

# Try it out:
print(spelling_hash[['ABANDONNED']])  # prints ABANDONED

# Now make a function to apply the lookup - and ensure
# if the string is not in the lookup table, you return the 
# original string instead (instead of NULL)
apply_hash <- function(in_string, hash_table=spelling_hash){
  x = hash_table[[in_string]]
  if(!is.null(x)){
    return(x)
  }
  else{
    return(in_string)
  }
}

# Finally make a function to break the full company name apart, 
# apply the lookup on each word, and then paste it back together
correct_spelling <- function(bad_string) {
  split_string <- strsplit(as.character(bad_string), " ")
  new_split <- lapply(split_string[[1]], apply_hash)
  return(paste(new_split, collapse=' '))
}

# Make a new field that applies the spelling correction
Orgs$Corrected <- sapply(Orgs$OrgName, correct_spelling)
...