web-dev-qa-db-ja.com

正規表現は機能していますが、コードは恐ろしいようです

さらなるテキストマイニングのために、名詞句の長いリストを整理しています。 1ワードまたは2ワードのフレーズを想定していますが、一部に/が含まれています。ここに私が持っているものがあります:

library(tidyverse)
conjuncts <- tibble(usecase = 1:3,
                   classes = c("Insulators/Insulation",
                               "Optic/light fiber",
                               "Magnets"))

そして私は欲しい:

wanted <- tibble(usecase = c(1,1,2,2,3),
                 classes =  c("Insulators/Insulation",
                              "Insulators/Insulation",
                              "Optic/light fiber",
                              "Optic/light fiber",
                              "Magnets"),
                 bigrams = c("Insulators", "Insulation",
                             "Optic fiber", "Light fiber", NA))

私は何か機能していますが、それは恐ろしくて拡張不可能です。

patternSplit <- function(class){
  regexs <- c("(?x) ^ (\\w+) / (\\w+) $",
              "(?x) ^ (\\w+) / (\\w+) \\s+ (\\w+) $")
  if(str_detect(class, regexs[1])){
    extr <- str_match(class, regexs[1])
    list(extr[1,2],
         extr[1,3]) 
  } else if(str_detect(class, regexs[2])){
    extr <- str_match(class, regexs[2])
    list(paste(extr[1,2], extr[1,4]), 
         paste(extr[1,3], extr[1,4])) 
  } else {
    list(NA_character_)
  }
}

anx <- conjuncts %>% 
  mutate(bigrams = map(classes, patternSplit)) %>% 
  unnest(cols = "bigrams") %>% 
  unnest(cols = "bigrams")

それは私が欲しかったものを私に与えます、しかしblecchh

# A tibble: 5 x 3
  usecase classes               bigrams    
    <int> <chr>                 <chr>      
1       1 Insulators/Insulation Insulators 
2       1 Insulators/Insulation Insulation 
3       2 Optic/light fiber     Optic fiber
4       2 Optic/light fiber     light fiber
5       3 Magnets               NA         

上位2つの問題(1)rexexを2回実行する必要があります。1回はstr_detectの論理を取得するためにif / elseを使用し、もう1つはstr_matchを使用してトークンを引き出します。 (2)リスト構造をほどくために二重のunnestをしました。さらに小さな問題(3)if / elseからcase_whenまたはswitchに脱出できますか?

私は最終的にこれを約12のパターンとユースケースに拡張する予定です。

4
David T

以下は、/をセパレーターとして使用してWordフレーズを検出し、ifelseを使用して望ましい結果を得るソリューションです。

patternSplit<- function(x,p="[A-z]+[/][A-z]+"){
  x1<- stringr::str_extract(x,p)
  x2<- stringr::str_replace(x,p,"")
  return(cbind(val1=x1,val2=x2))
}

conjuncts<- cbind(conjuncts,conjuncts$classes %>% patternSplit()) %>% 
  tidyr::separate_rows(val1, sep = '/') %>% 
  dplyr::mutate(bigrams= ifelse(!is.na(val1),paste0(val1,val2),val1)) %>%
  dplyr::select(-contains("val"))

conjuncts
  usecase               classes     bigrams
1       1 Insulators/Insulation  Insulators
2       1 Insulators/Insulation  Insulation
3       2     Optic/light fiber Optic fiber
4       2     Optic/light fiber light fiber
5       3               Magnets        <NA>
1
rj-nirbhay