8

Karl Broman の投稿: https://kbroman.wordpress.com/2015/06/22/randomized-hobbit-2/は、楽しみのためだけに正規表現と ngram をいじることになりました。正規表現を使用して 2 グラムを抽出しようとしました。これを行うためのパーサーがあることは知っていますが、正規表現ロジックに興味があります (つまり、私が満たすことができなかったのは自己課題でした)。

以下に、最小限の例と目的の出力を示します。私の試みの問題は2つあります:

  1. グラム (単語) が消費され、次のパスで使用できなくなります。 2 番目のパスでそれらを使用できるようにするにはどうすればよいですか? (例: で以前に消費された後にlike利用できるようにしたい)like toastI like

  2. 単語間のスペースを非キャプチャにすることはできませんでした ( を使用したにもかかわらず、出力の末尾の空白に注意して(?:\\s*)ください)。 n 番目 (この場合は 2 番目) の単語の末尾のスペースをキャプチャしないようにするにはどうすればよいですか? これは簡単に実行できることを知っています:"(\\b[A-Za-z']+\\s)(\\b[A-Za-z']+)"2グラムの場合ですが、ソリューションをnグラムに拡張したいと思います。PS私は知って\\wいますが、アンダースコアと数字を単語の一部とは見なしませんが'、単語の一部と見なします。

MWE:

library(stringi)

x <- "I like toast and jam."

stringi::stri_extract_all_regex(
    x,
    pattern = "((\\b[A-Za-z']+\\b)(?:\\s*)){2}"
)

## [[1]]
## [1] "I like "    "toast and "

望ましい出力:

## [[1]]
## [1] "I like"  "like toast"    "toast and"  "and jam"
4

2 に答える 2

8

ベース R 正規表現を使用する 1 つの方法を次に示します。これは、任意の n-gram を処理するように簡単に拡張できます。秘訣は、キャプチャ グループを肯定的な先読みアサーション内に配置することです。(?=(my_overlapping_pattern))

x <- "I like toast and jam."
pattern <- "(?=(\\b[A-Za-z']+\\b \\b[A-Za-z']+\\b))"
matches<-gregexpr(pattern, x, perl=TRUE)
# a little post-processing needed to get the capture groups with regmatches
attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1])
regmatches(x, matches)

# [[1]]
# [1] "I like"     "like toast" "toast and"  "and jam"
于 2015-06-23T13:14:03.117 に答える
2

実際、そのためのアプリがあります:quantedaパッケージ (テキストデータの定量分析用)。共著者の Paul Nulty と私はこれを改善するために懸命に取り組んでいますが、あなたが説明したユースケースを簡単に処理できます。

install.packages("quanteda")
require(quanteda)
x <- "I like toast and jam."
> ngrams(x, 2)
## [[1]]
## [1] "i_like"     "like_toast" "toast_and"  "and_jam"   
ngrams(x, n = 2, concatenator = " ", toLower = FALSE)
## [[1]]
## [1] "I like"     "like toast" "toast and"  "and jam"   

面倒な正規表現は必要ありません!

于 2015-06-23T15:04:49.477 に答える