web-dev-qa-db-ja.com

文字列間のレーベンシュタイン距離を計算するために行われた操作を知る方法は?

関数stringdistを使用すると、文字列間のレーベンシュタイン距離を計算できます。これは、文字列を別の文字列に変換するために必要な削除、挿入、置換の数を数えます。たとえば、2番目の文字列に「d」が挿入されたため、stringdist("abc abc","abcd abc") = 1になります。

2つのストリング間のレーベンシュタイン距離を取得するために行われた操作を知ることは可能ですか?または、2つの文字列の間で異なる文字(この例では「d」のみ)を知るには?ありがとう。

library(stringdist)
stringdist("abc abc","abcde acc") = 3

私はそれを知りたいです:

  • 「d」が挿入されました

  • 「e」が挿入されました

  • 「b」は「c」に置き換えられました

もっと簡単に言うと、リスト( "d"、 "e"、 "c")が欲しいです。

9
yaki

これは Needleman–Wunschアルゴリズム として知られています。 2つの文字列間の距離と、いわゆるtracebackの両方を計算します。これにより、配置を再構築できます。

この問題は生物学的シーケンスを比較するときに生物学で主に発生するため、このアルゴリズム(および関連するアルゴリズム)はRパッケージ {Biostrings} に実装されており、これは Bioconductor の一部です。

このパッケージの実装は単純なレーベンシュタイン距離よりも一般的なソリューションであるため、使用法は残念ながらより複雑であり、それに応じて sage vignette は長くなります。ただし、目的の基本的な使用法は次のとおりです。

_library(Biostrings)

dist_mat = diag(27L)
colnames(dist_mat) = rownames(dist_mat) = c(letters, ' ')

result = pairwiseAlignment(
    "abc abc", "abcde acc",
    substitutionMatrix = dist_mat,
    gapOpening = 1, gapExtension = 1
)
_

ただし、これはc('b', 'c', 'c')というリストを提供するだけではありません。このリストは、実際にここで起こったことを完全には表していないためです。代わりに、2つの文字列間のalignmentを返します。これは、置換とギャップのあるシーケンスとして表すことができます。

_score(result)
# [1] 3
aligned(result)
as.matrix(aligned(result))
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
# [1,] "a"  "b"  "c"  "-"  "-"  " "  "a"  "b"  "c"
aligned(result)
_

— 2番目の文字列の各文字について、元の文字列の対応する文字を提供し、挿入された文字を_-_で置き換えます。基本的に、これは最初の文字列を2番目の文字列に変換するための「レシピ」です。挿入と置換のみが含まれ、削除は含まれないことに注意してください。これらを取得するには、逆方向に配置する(つまり、文字列引数を交換する)必要があります。

8
Konrad Rudolph

adist()を使用すると、操作を取得できます。

drop(attr(adist("abc abc","abcde acc", count = TRUE), "counts"))

ins del sub 
  2   0   1 

?adistから:

CountsがTRUEの場合、変換カウントは、この行列の「counts」属性として、xの要素、yの要素、および変換のタイプ(挿入、削除、および置換)、それぞれ。

10
tmfmnk