두 벡터의 문자열 (R)을 유사하게 일치시키는 방법은 무엇입니까?


36

이것이 어떻게 표시되어야하는지 잘 모르겠으므로 더 나은 용어를 알고 있다면 수정 해주세요.

두 가지 목록이 있습니다. 55 개 항목 중 하나 (예 : 문자열 벡터), 92 개 중 다른 항목. 항목 이름은 비슷하지만 동일하지는 않습니다.

나는 최선의 후보를 찾고자 55 목록의 항목 (I는 다음을 통해 이동하고 올바른 피팅을 선택할 것)에 92 목록에.

어떻게 할 수 있습니까?

내가 어디에서 아이디어를 얻었습니까?

  1. 일치하는 항목을 모두보십시오 (일부 목록 사용? 일치)
  2. 문자열 벡터 사이의 거리 행렬을 사용해보십시오. 그러나 그것을 가장 잘 정의하는 방법을 모르겠습니다 (동일한 문자 수, 문자열 순서는 어떻습니까?)

그렇다면 어떤 패키지 / 기능 / 연구 분야가 그러한 작업을 어떻게 처리합니까?

업데이트 : 다음은 일치시킬 벡터의 예입니다.

vec55 <- c("Aeropyrum pernix", "Archaeoglobus fulgidus", "Candidatus_Korarchaeum_cryptofilum", 
"Candidatus_Methanoregula_boonei_6A8", "Cenarchaeum_symbiosum", 
"Desulfurococcus_kamchatkensis", "Ferroplasma acidarmanus", "Haloarcula_marismortui_ATCC_43049", 
"Halobacterium sp.", "Halobacterium_salinarum_R1", "Haloferax volcanii", 
"Haloquadratum_walsbyi", "Hyperthermus_butylicus", "Ignicoccus_hospitalis_KIN4", 
"Metallosphaera_sedula_DSM_5348", "Methanobacterium thermautotrophicus", 
"Methanobrevibacter_smithii_ATCC_35061", "Methanococcoides_burtonii_DSM_6242"
)
vec91 <- c("Acidilobus saccharovorans 345-15", "Aciduliprofundum boonei T469", 
"Aeropyrum pernix K1", "Archaeoglobus fulgidus DSM 4304", "Archaeoglobus profundus DSM 5631", 
"Caldivirga maquilingensis IC-167", "Candidatus Korarchaeum cryptofilum OPF8", 
"Candidatus Methanoregula boonei 6A8", "Cenarchaeum symbiosum A", 
"Desulfurococcus kamchatkensis 1221n", "Ferroglobus placidus DSM 10642", 
"Halalkalicoccus jeotgali B3", "Haloarcula marismortui ATCC 43049", 
"Halobacterium salinarum R1", "Halobacterium sp. NRC-1", "Haloferax volcanii DS2", 
"Halomicrobium mukohataei DSM 12286", "Haloquadratum walsbyi DSM 16790", 
"Halorhabdus utahensis DSM 12940", "Halorubrum lacusprofundi ATCC 49239", 
"Haloterrigena turkmenica DSM 5511", "Hyperthermus butylicus DSM 5456", 
"Ignicoccus hospitalis KIN4/I", "Ignisphaera aggregans DSM 17230", 
"Metallosphaera sedula DSM 5348", "Methanobrevibacter ruminantium M1", 
"Methanobrevibacter smithii ATCC 35061", "Methanocaldococcus fervens AG86", 
"Methanocaldococcus infernus ME", "Methanocaldococcus jannaschii DSM 2661", 
"Methanocaldococcus sp. FS406-22", "Methanocaldococcus vulcanius M7", 
"Methanocella paludicola SANAE", "Methanococcoides burtonii DSM 6242", 
"Methanococcus aeolicus Nankai-3", "Methanococcus maripaludis C5", 
"Methanococcus maripaludis C6", "Methanococcus maripaludis C7", 
"Methanococcus maripaludis S2", "Methanococcus vannielii SB", 
"Methanococcus voltae A3", "Methanocorpusculum labreanum Z", 
"Methanoculleus marisnigri JR1", "Methanohalobium evestigatum Z-7303", 
"Methanohalophilus mahii DSM 5219", "Methanoplanus petrolearius DSM 11571", 
"Methanopyrus kandleri AV19", "Methanosaeta thermophila PT", 
"Methanosarcina acetivorans C2A", "Methanosarcina barkeri str. Fusaro", 
"Methanosarcina mazei Go1", "Methanosphaera stadtmanae DSM 3091", 
"Methanosphaerula palustris E1-9c", "Methanospirillum hungatei JF-1", 
"Methanothermobacter marburgensis str. Marburg", "Methanothermobacter thermautotrophicus str. Delta H", 
"Nanoarchaeum equitans Kin4-M", "Natrialba magadii ATCC 43099", 
"Natronomonas pharaonis DSM 2160", "Nitrosopumilus maritimus SCM1", 
"Picrophilus torridus DSM 9790", "Pyrobaculum aerophilum str. IM2", 
"Pyrobaculum arsenaticum DSM 13514", "Pyrobaculum calidifontis JCM 11548", 
"Pyrobaculum islandicum DSM 4184", "Pyrococcus abyssi GE5", "Pyrococcus furiosus DSM 3638", 
"Pyrococcus horikoshii OT3", "Staphylothermus hellenicus DSM 12710", 
"Staphylothermus marinus F1", "Sulfolobus acidocaldarius DSM 639", 
"Sulfolobus islandicus L.D.8.5", "Sulfolobus islandicus L.S.2.15", 
"Sulfolobus islandicus M.14.25", "Sulfolobus islandicus M.16.27", 
"Sulfolobus islandicus M.16.4", "Sulfolobus islandicus Y.G.57.14", 
"Sulfolobus islandicus Y.N.15.51", "Sulfolobus solfataricus P2", 
"Sulfolobus tokodaii str. 7", "Thermococcus gammatolerans EJ3", 
"Thermococcus kodakarensis KOD1", "Thermococcus onnurineus NA1", 
"Thermococcus sibiricus MM 739", "Thermofilum pendens Hrk 5", 
"Thermoplasma acidophilum DSM 1728", "Thermoplasma volcanium GSS1", 
"Thermoproteus neutrophilus V24Sta", "Thermosphaera aggregans DSM 11486", 
"Vulcanisaeta distributa DSM 14429", "uncultured methanogenic archaeon RC-I"
) 

2
Hi Tal :> 이것들이 오타가없는 과학적인 이름 인 것처럼 보이면, 먼저 Levenshtein 메트릭을 (92 x 55 거리 매트릭스의 맥락에서) 시도하고 어떻게 나오는지 봅니다.
user603

2
얼마 후, stringdist패키지는 이런 종류의 일에 가장 적합한 리소스 인 것 같습니다.
shabbychef

답변:


18

비슷한 문제가있었습니다. (여기에서 참조 : https://stackoverflow.com/questions/2231993/merging-two-data-frames-using-fuzzy-approximate-string-matching-in-r )

내가받은 권장 사항은 대부분 다음과 같습니다.

pmatch()그리고 agrep(), grep(), grepl()세 가지 기능은 당신이 대략 문자열이나 대략적인 정규 표현식로 인해서 대략적인 문자열 일치에 대한 통찰력을 제공합니다 통해 보는 시간이 걸릴 경우 그.

문자열을 보지 않으면 문자열을 일치시키는 방법에 대한 어려운 예를 제공하기가 어렵습니다. 예제 데이터를 제공 할 수 있다면 해결책을 찾게 될 것입니다.

내가 찾은 또 다른 옵션은 문자열을 평평하게하여 문자열 tolower()내의 각 단어의 첫 글자를보고 비교하는 것입니다. 때로는 문제없이 작동합니다. 그런 다음 다른 답변에서 언급 된 거리와 같은 더 복잡한 것들이 있습니다. 때로는 이러한 작업, 때로는 끔찍한 일입니다. 실제로 문자열에 달려 있습니다.

우리가 그들을 볼 수 있습니까?

최신 정보

agrep ()이 대부분의 트릭을 수행하는 것처럼 보입니다. agrep ()은 R의 Levenshtein 거리 구현입니다.

agrep(vec55[1],vec91,value=T)

일부는 계산하지 않지만 Ferroplasm acidaramus가 Ferroglobus placidus DSM 10642와 같은지 확실하지 않습니다.

agrep(vec55[7],vec91,value=T) 

나는 당신이 이것들 중 일부에 대해 약간 SOL 일 수 있다고 생각하며 처음부터 인덱스를 만드는 것이 가장 좋은 방법입니다. 즉. vec55에 대한 id 번호가있는 테이블을 작성한 다음 vec91의 vec55에있는 id에 대한 참조를 수동으로 작성하십시오. 고통 스럽지만, agrep ()로 많은 것을 할 수 있습니다.


안녕 브랜든-데이터 샘플을 추가했습니다. 감사!
탈 Galili

안녕 브랜든-귀하의 솔루션이 훌륭하게 작동했습니다-감사합니다.
탈 Galili

SE의 주제에 대한 이전 질문에 대한 링크의 경우 +1 (agrep ()에 대한 포인터를 입력합니다).
user603

15

두 줄 사이의 거리를 측정하는 방법에는 여러 가지가 있습니다. R에서 널리 구현 된 두 가지 중요한 (표준) 접근 방식은 Levenshtein과 Hamming 거리입니다. 전자는 패키지 'MiscPsycho'에서 사용 가능하고 후자는 'e1071'에서 사용 가능합니다. 이것들을 사용하여 간단히 92 x 55 쌍의 거리 행렬을 계산 한 다음 거기에서 진행합니다 (즉, 목록 1에서 문자열 "1"에 가장 적합한 후보 일치는 목록 2에서 문자열 "1까지의 거리가 가장 작은 문자열"x "입니다) ").

또는 RecordLinkage 패키지에 compare () 함수가 있습니다.이 기능은 원하는 작업을 수행하도록 설계되었으며 소위 Jaro-Winkler distance 를 사용하여 현재 작업에 더 적합한 것으로 보이지만 경험이 없습니다. .

편집 : 브랜든의 의견뿐만 아니라 탈의 코드, "에로 피 룸속의 pernix"에 일치하는 항목을 찾을 수의 첫 번째 항목 포함하도록 내 대답을 편집하고있어 vec55를 :

agrep(vec55[1],vec91,ignore.case=T,value=T,max.distance = 0.1, useBytes = FALSE)
[1] "Aeropyrum pernix K1"

8
+1. 또한 도움이되는 경우 문자열을 비교할 때 Google에서 사용하는 용어는 "편집 거리"입니다. en.wikipedia.org/wiki/Edit_distance
ars

@ars :> 고마워, 그것은 R 검색 엔진에 공급하고 나오는 것을 보는 편리한 목록입니다!
user603

2
Levenshtein 편집 거리 () agrep이를 통해 기본 패키지의 일부로서 구현
브랜든 Bertelsen

큰 답변 Kwak-앞으로 살펴볼 것입니다!
탈 Galili

개인적으로 이것은 이것이 Tal의 질문에 대한 더 완전한 대답이라고 생각합니다. RecordLinkage를 지적 해 주신 +1-반드시 시도해야합니다.
Brandon Bertelsen

7

Kwak의 유용한 답변을 보완하기 위해 간단한 원칙과 아이디어를 추가하겠습니다. 메트릭을 결정하는 좋은 방법은 문자열이 대상과 어떻게 다른지 고려하는 것입니다. "거리 수정"은 변형이 이웃을 바꾸거나 단일 키를 잘못 입력하는 것과 같은 인쇄상의 오류의 조합 일 때 유용합니다.

약간 다른 철학을 가진 또 다른 유용한 접근 방식은 모든 문자열을 관련 문자열 클래스를 나타내는 하나의 매핑으로 매핑하는 것입니다. " Soundex "방법은 다음을 수행합니다. 단어에 대한 Soundex 코드는 주요 자음과 비슷한 소리의 내부 결과 그룹을 인코딩하는 4 개의 문자 시퀀스입니다. 단어가 철자가 틀린 철자이거나 다른 단어 일 때 사용됩니다. 예제 애플리케이션에서는 Soundex 코드가 각 프로브 단어에 대한 Soundex 코드와 동일한 모든 대상 단어를 가져옵니다. (이 방법으로 가져 오는 대상이 없거나 여러 개일 수 있습니다.)


3

또한 Kwak의 다른 제안 외에도 N-gramDamerau-Levenshtein 거리 를 확인하는 것이 좋습니다 .

논문 은 여기에 언급 된 몇 가지 다른 편집 거리의 정확도를 비교합니다 (Google 학자에 따르면 많이 인용됩니다).

보시다시피 여기에 접근하는 방법에는 여러 가지가 있으며 다른 메트릭스 (이 약간의 이야기에 연결된 논문)를 결합 할 수도 있습니다. Levenshtein 및 관련 기반 메트릭은 특히 사람이 입력하여 오류가 발생하는 경우 가장 직관적으로 이해됩니다. N- 그램도 단순하며 이름이나 단어가 아닌 데이터에 적합합니다.

soundex는 옵션이지만, 내가 본 약간의 작업 (아주 소량 임) soundex는 이름이 일치하는 Levenshstein 또는 기타 편집 거리만큼 성능이 좋지 않습니다. 그리고 Soundex는 Levenshtein과 N-gram이 잠재적으로 더 넓은 범위를 가질 때 (특히 N-gram이지만 Levenshtein 거리는 비 단어에서도 더 잘 수행 될 것으로 예상 됨) 인간 입력기에 의해 입력 될 수있는 음성 표현으로 제한됩니다.

나는 패키지까지는 도울 수 없지만 N 그램의 개념은 매우 간단합니다 (최근에 N 그램을 수행하기 위해 SPSS 매크로를 만들었지 만 작은 프로젝트의 경우 이미 만들어진 패키지를 사용합니다) R은 다른 포스터가 제안했다. 다음 은 파이썬에서 Levenshtein 거리를 계산하는 예입니다.


앤디 감사합니다-앞으로 살펴볼 것입니다.
탈 Galili

1

나는이 문제를 해결하는 방법과 패키지를 연구했으며 가장 좋은 후보는 fuzzywuzzyR패키지 라고 생각합니다 .

fuzzywuzzyR 패키지는 fuzzywuzzy python 패키지 의 퍼지 문자열 일치 구현입니다 . Levenshtein Distance를 사용하여 시퀀스 간 차이를 계산합니다. fuzzywuzzyR의 기능에 대한 자세한 내용은 블로그 게시물 및 Vignette 패키지에서 찾을 수 있습니다 .

귀하의 문제에 대한 간단한 해결책을 제시했지만 약간의 문제가 있습니다. python을 설치해야하고 winodows를 사용하는 경우 Visual Studio 용 빌드 도구도 설치해야합니다 . 다음을 선택해야합니다.

  • Windows 10 SDK 10.0.17763.0 및 MSVC v140
  • VS 2015 C ++ 빌드 도구 (v 14v00)

해결책은 간단합니다. 주 함수 ExtractOne는 두 값의 목록을 반환합니다. 첫 번째는 하나의 문자열 일치이고 두 번째는 해당 점수입니다 (0-100 범위). fuzzywuzzyR패키지는 유용 할 수있는 다른 기능을 제공합니다. 주요 문서는 여기 에서 찾을 수 있습니다 . 이 코드가 문제 해결에 도움이되기를 바랍니다.

library(fuzzywuzzyR)

# The Fuzzy initialization
init_proc = FuzzUtils$new()
PROC = init_proc$Full_process # class process-method
PROC1 = tolower # base R function
init_scor = FuzzMatcher$new()
SCOR = init_scor$WRATIO    
init <- FuzzExtract$new()

match_strings <- function(vector_to_process, base_vector){  
  new_vec = c()
  for(i in 1:length(vector_to_process)){      
    new_word <- init$ExtractOne(string = vector_to_process[i], sequence_strings = base_vector, processor = PROC1, scorer = SCOR, score_cutoff = 0L)
    new_vec[i] <- new_word[[1]]
  }     
  return(new_vec)
}

# Check if all python modules are available
if (check_availability()){    
  new_vec <- match_strings(vec55, vec91)
  print(new_vec)   
}

산출:

[1] "Aeropyrum pernix K1"                                 "Archaeoglobus fulgidus DSM 4304"                    
[3] "Candidatus Korarchaeum cryptofilum OPF8"             "Candidatus Methanoregula boonei 6A8"                
[5] "Cenarchaeum symbiosum A"                             "Desulfurococcus kamchatkensis 1221n"                
[7] "Thermoplasma volcanium GSS1"                         "Haloarcula marismortui ATCC 43049"                  
[9] "Halobacterium sp. NRC-1"                             "Halobacterium salinarum R1"                         
[11] "Haloferax volcanii DS2"                              "Haloquadratum walsbyi DSM 16790"                    
[13] "Hyperthermus butylicus DSM 5456"                     "Ignicoccus hospitalis KIN4/I"                       
[15] "Metallosphaera sedula DSM 5348"                      "Methanothermobacter thermautotrophicus str. Delta H"
[17] "Methanobrevibacter smithii ATCC 35061"               "Methanococcoides burtonii DSM 6242"       

0

기능 기반 adist

문자형 벡터 사이의 대략적인 문자열 거리를 계산합니다. 거리는 일반화 된 레 벤슈 테인 (편집) 거리이며, 한 문자열을 다른 문자열로 변환하는 데 필요한 최소 가중 삽입, 삭제 및 대체 횟수를 제공합니다.

stringdist이름이 같은 패키지의 함수 에는 여러 가지 방법이 있습니다 (참조 ?stringdist).

method = c ( "osa", "lv", "dl", "hamming", "lcs", "qgram", "cosine", "jaccard", "jw", "soundex")

이를 통해 최대 발산 (임계 값)을 선택할 수 있습니다.

firstvector<-vec55
secondvector<-vec91

match<-character()
threshold<-14 # max 14 characters of divergence
mindist<-integer()
sortedmatches<-character()

for (i in 1:length(firstvector) ) {
  matchdist<-adist(firstvector[i],secondvector)[1,]
  # matchdist<-stringdist(firstvector[i],secondvector) # several methods available

  matchdist<-ifelse(matchdist>threshold,NA,matchdist)
  sortedmatches[i]<-paste(secondvector[order(matchdist, na.last=NA)], collapse = ", ")
  mindist[i]<- tryCatch(ifelse(is.integer(which.min(matchdist)),matchdist[which.min(matchdist)],NA), error = function(e){NA})
  match[i]<-ifelse(length(secondvector[which.min(matchdist)])==0,NA,
                  secondvector[which.min(matchdist)] )
}
res<-data.frame(firstvector=firstvector,match=match,divergence=mindist, sortedmatches=sortedmatches, stringsAsFactors = F)
res

이 데이터 프레임은 열 firstvector의 첫 번째 벡터, 열 일치의 두 번째 벡터의 최고 일치, 열 발산 거리 및 OP에서와 같이 열 정렬 된 일치 순서로 정렬 된 모든 중요한 일치를 보여줍니다.


2
구현은 종종 실질적인 내용과 혼합되지만, 우리는 코드가 아닌 통계, 머신 러닝 등에 관한 정보를 제공하는 사이트가되어야합니다. 코드를 제공하는 것도 좋지만 코드에서 답을 인식하고 추출하기에이 언어를 충분히 읽지 못하는 사람들을 위해 실질적인 답변을 텍스트로 정교하게 작성하십시오.
gung-모니 티 복원
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.