Code
dat_txt <-
tibble::tibble(
doc_id = seq_along(audubon::polano) |> as.character(),
text = audubon::polano
) |>
dplyr::mutate(text = audubon::strj_normalize(text))
dat <- gibasa::tokenize(dat_txt, text, doc_id)
dat_count <- dat |>
gibasa::prettify(col_select = c("POS1", "Original")) |>
dplyr::filter(POS1 %in% c("名詞", "動詞", "形容詞")) |>
dplyr::mutate(
doc_id = forcats::fct_drop(doc_id),
token = dplyr::if_else(is.na(Original), token, Original)
) |>
dplyr::count(doc_id, token)
文書内での共起
共起関係を数える機能はgibasaには実装されていません。文書内での共起を簡単に数えるには、たとえば次のようにします。
dat_fcm <- dat_count |>
tidytext::cast_dfm(doc_id, token, n) |>
quanteda::fcm()
dat_fcm
#> Feature co-occurrence matrix of: 2,172 by 2,172 features.
#> features
#> features ポラーノ 広場 宮沢 賢治 レオーノ・キュースト 七 十 官 等
#> ポラーノ 5 52 0 0 0 0 2 0 0
#> 広場 0 5 0 0 0 0 2 0 0
#> 宮沢 0 0 0 2 0 0 0 0 0
#> 賢治 0 0 0 0 0 0 0 0 0
#> レオーノ・キュースト 0 0 0 0 0 1 3 3 3
#> 七 0 0 0 0 0 0 9 1 1
#> 十 0 0 0 0 0 0 8 6 6
#> 官 0 0 0 0 0 0 0 0 5
#> 等 0 0 0 0 0 0 0 0 0
#> 誌 0 0 0 0 0 0 0 0 0
#> features
#> features 誌
#> ポラーノ 0
#> 広場 0
#> 宮沢 0
#> 賢治 0
#> レオーノ・キュースト 1
#> 七 1
#> 十 1
#> 官 1
#> 等 1
#> 誌 0
#> [ reached max_feat ... 2,162 more features, reached max_nfeat ... 2,162 more features ]
任意のウィンドウ内での共起
共起の集計
RMeCab::collocate
のような任意のウィンドウの中での共起を集計するには、次のようにする必要があります。ここではwindowは前後5個のトークンを見るようにします。
dat_corpus <- dat |>
gibasa::pack()
dat_fcm <- dat_corpus |>
quanteda::corpus() |>
quanteda::tokens(what = "fastestword") |>
quanteda::fcm(context = "window", window = 5)
こうすると、nodeについて共起しているtermとその頻度を確認できます。以下では、「わたくし」というnodeと共起しているtermで頻度が上位20までであるものを表示しています。
dat_fcm <- dat_fcm |>
tidytext::tidy() |>
dplyr::rename(node = document, term = term) |>
dplyr::filter(node == "わたくし") |>
dplyr::slice_max(count, n = 20)
dat_fcm
#> # A tibble: 20 × 3
#> node term count
#> <chr> <chr> <dbl>
#> 1 わたくし は 205
#> 2 わたくし 。 122
#> 3 わたくし た 110
#> 4 わたくし て 99
#> 5 わたくし 、 91
#> 6 わたくし まし 90
#> 7 わたくし を 62
#> 8 わたくし に 61
#> 9 わたくし が 51
#> 10 わたくし し 37
#> 11 わたくし も 35
#> 12 わたくし で 33
#> 13 わたくし ども 28
#> 14 わたくし と 23
#> 15 わたくし 」 23
#> 16 わたくし です 22
#> 17 わたくし へ 17
#> 18 わたくし い 15
#> 19 わたくし 「 15
#> 20 わたくし から 14
T値やMI値の算出
T値やMI値は、たとえば次のようにして計算できます。
T値については「1.65」を越える場合、その共起が偶然ではないと考える大まかな目安となるそうです。また、MI値については「1.58」を越える場合に共起関係の大まかな目安となります(いずれの値についても「2」などを目安とする場合もあります)。
ntok <- dat_corpus |>
quanteda::corpus() |>
quanteda::tokens(what = "fastestword") |>
quanteda::ntoken() |>
sum()
total <- dat_corpus |>
quanteda::corpus() |>
quanteda::tokens(what = "fastestword") |>
quanteda::tokens_select(c("わたくし", dat_fcm$term)) |>
quanteda::dfm() |>
quanteda::colSums()
dat_fcm |>
dplyr::select(-node) |>
dplyr::mutate(
expect = total[term] / ntok * total["わたくし"] * 5 * 2, ## 5はwindowのサイズ
t = (count - expect) / sqrt(count),
mi = log2(count / expect)
)
#> # A tibble: 20 × 5
#> term count expect t mi
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 は 205 88.1 8.17 1.22
#> 2 。 122 161. -3.53 -0.400
#> 3 た 110 108. 0.190 0.0264
#> 4 て 99 106. -0.694 -0.0972
#> 5 、 91 102. -1.13 -0.162
#> 6 まし 90 64.1 2.73 0.489
#> 7 を 62 67.4 -0.689 -0.121
#> 8 に 61 68.8 -1.00 -0.174
#> 9 が 51 51.9 -0.126 -0.0252
#> 10 し 37 24.1 2.11 0.616
#> 11 も 35 31.4 0.615 0.158
#> 12 で 33 34.7 -0.290 -0.0710
#> 13 ども 28 3.11 4.70 3.17
#> 14 と 23 28.7 -1.18 -0.317
#> 15 」 23 54.8 -6.63 -1.25
#> 16 です 22 15.4 1.40 0.512
#> 17 へ 17 16.5 0.114 0.0403
#> 18 い 15 17.4 -0.628 -0.217
#> 19 「 15 56.2 -10.6 -1.91
#> 20 から 14 20.4 -1.72 -0.546
注意点として、quantedaは全角スペースなどをトークンとして数えないようなので、ここでの総語数(ntok
)は、RMeCabの計算で使われる総語数よりも少なくなることがあります。RMeCabでの計算結果と概ね一致させたい場合は、総語数としてgibasa::tokenize
の戻り値の行数を使ってください。