3

stringdistパッケージまたは別の文字列距離パッケージを使用して特定の単語に重みを付ける方法はありますか?

多くの場合、"city" や "university" などの一般的な単語を共有する文字列があり、結果として比較的近い文字列距離の一致が得られますが、非常に異なります (例: "University of Utah" と "University of Ohio"、または " XYZ市」および「ABC市」)。

アルゴリズムによって操作 (削除、挿入、置換) の重み付けが異なることは知っていますが、重み付けされた単語のリストを含める方法は見たことがありません。何かご意見は?

確かstr_removeに、一致する前にこれらの一般的な単語に対する 1 つのオプションがありますが、これには「XYZ 郡」と「XYZ 市」が同一に見えるという問題があります。

例:

「ユタ大学」と「オハイオ大学」

stringdist("University of Utah", "University of Ohio") / max(nchar("University of Utah"), nchar("University of Ohio"))

正規化されたストリング距離は 0.22222 です。これは比較的低いです。しかし実際には、「ユタ」と「オハイオ」の間の正規化された OSA 文字列距離は 1 です。

4 / 18 = 0.222222

ただし、「University of」や「State」などの一般的な文字列を事前に削除すると、「University of Ohio」と「Ohio State」が一致することになります。

"University of" のような文字列を重み付けして、たとえば、正規化分母で使用される実際の文字数の 0.25 をカウントすると、これらの共通部分文字列の影響が軽減されます。つまり、次のようになります。

4 / (18 * 0.25) = 0.888888。

State vs University の例で同じことを考えると、ここではあいまいになります。

stringdist("University of Ohio", "Ohio State")

16 が得られます。ただし、分母の .25 を使用すると、次のようになります。

16 / (18 * .25) = 3.55555。

おそらくより良いオプションは、LCS を使用することですが、一般的な文字列のリストに一致する部分文字列を軽量化することです。したがって、「University of Utah」と「University of Ohio」には 14 文字の共通部分文字列がありますが、「University of」がこのリストに表示された場合、その LCS 値は減少します。

編集:別の考え

tidytextpackage とを使用するとunnest_tokens、一致するすべての文字列で最も一般的な単語のリストを生成できます。データセット内の共通性に関連してこれらの単語の重みを下げることを検討することは興味深いかもしれません。それらがより一般的であるほど、それらの差別化力が少なくなるためです...

4

1 に答える 1

2

おそらく、「オハイオ州」と「オハイオ大学」を完全に比較することを避けるために、文字列の距離を計算する前に類似の用語を再グループ化することが 1 つの考えかもしれません。

# Strings
v1 <- c("University of Ohio", "University of Utah", "Ohio State", "Utah State",
        "University Of North Alabama", "University of South Alabama", "Alabama State",
        "Arizona State University Polytechnic", "Arizona State University Tempe", 
        "Arizona State", "Metropolitan State University of Denver", 
        "Metropolitan University Of The State Of Denver", "University Of Colorado", 
        "Western State Colorado University", "The Dalton College", "The Colorado State", 
        "The Dalton State College", "Columbus State University", "Dalton College")

# Remove stop words
v2 <- strsplit(v1, " ") %>% 
  map_chr(~ paste(.x[!tolower(.x) %in% tm::stopwords()], collapse = " "))

# Define groups
groups <- c(Group1 = "state", 
            Group2 = "university", 
            Group3 = "college",
            # Groups 4-5 must contain BOTH terms
            Group4 = ".*(state.*university|university.*state).*", 
            Group5 = ".*(state.*college|college.*state).*")

# Iterate over the list and assign groups
dat <- list(words = v2, pattern = groups)
lst <- dat$pattern %>% map(~ grepl(.x, dat$words, ignore.case = TRUE))

lst %>%
  # Make sure groups 1 to 3 and 4-5 are mutually exclusive
  # i.e: if a string contains "state" AND "university" (Group4), it must not be in Group1
  modify_at(c("Group1", "Group2", "Group3"), 
            ~ ifelse(lst$Group4 & .x | lst$Group5 & .x, !.x, .x)) %>%
  # Return matches from strings 
  map(~ v2[.x]) %>%
  # Compute the stringdistance for each group
  map(~ stringdistmatrix(.x, .x)) ## Maybe using method = "jw" ?
于 2018-05-26T17:35:35.240 に答える