この記事について
以前に書いた記事を焼き直ししつつ、ばんくしさんの以下のブログ記事のまねをRでやってみます。
ばんくしさんの記事は「Pythonどこまで脱却できるのか見るのも兼ねて」ということで、Rustで自然言語処理を試しています。私はべつに自然言語処理を実務でやるエンジニアとかではないですが、PythonじゃなくてRustとかGoといった静的型付けで速い言語で安全に書けたらうれしい場面があるよね、みたいなモチベーションなのかなと想像しています。
実際のところ、自分でコードを書きながら自然言語処理の真似事をするなら依然としてPythonが便利です。Rと比べても、PythonにはSudachiPyやjanomeといった選択肢がある一方で、RにはRコンソールからのみで導入が完了する形態素解析の手段が(少なくともCRANには)ありません。自然言語処理をやる言語としてPythonのほうがメジャーなことにはほかにもいくつかの理由というか経緯があるのでしょうが、Pythonを採用したほうがよいひとつのモチベーションとしては、テキストマイニングして得た特徴量を投入してディープラーニングをしたい場合は事実上Pythonを選択するしかないというのもある気がします。一応、{keras}や{torch}というのもありますが、このあたりのパッケージを使うのはまだ趣味の領域な気がします。
そうはいっても、{RMeCab}は強力なツールです。なぜかRからテキストマイニングに入ってしまった人間にとって、比較的簡単に導入できてほとんど環境を問わずすぐ使えるRMeCabは欠かせないツールだったことでしょう。ただ、Rに慣れてきていろいろなことをやってみたくなると、RMeCabは「なんか使いにくいな」みたいになりがちです。Rでも自然言語処理をやるためのパッケージは以下に紹介されているようにたくさんあるのですが、そもそも日本語情報があまりないし、そこそこがんばらないと詰まります。
💬 Neat overview of NLP tools in #rstats:
— Mara Averick (@dataandme) February 4, 2019
"An overview of the NLP ecosystem in R" by bnosachttps://t.co/PIKWFfTMPl
/* actual outline is a static doc */ pic.twitter.com/CyC6NhsIMa
でもまあRでもできなくはないんだよというのをしめす目的で、ここでは先の記事と同じようなことをRでやっていきます。
この記事のソース(R Markdown)は以下。
パッケージの選定にあたって
Tokenization
形態素解析などをやるパッケージとしては次に挙げるようなものがあります。知るかぎりではぜんぶ個人開発で、環境や使用する辞書、解析する文字列などによって上手く動いたり動かなかったりします。Neologd辞書を使うならRcppMeCabにすべきですが、メンテナの人が最近忙しいとかで、あまりアクティブに開発されていません。
- IshidaMotohiro/RMeCab: Interface to MeCab
- junhewk/RcppMeCab: RcppMeCab: Rcpp Interface of CJK Morpheme Analyzer MeCab
- uribo/sudachir: R Interface to 'Sudachi'
- paithiov909/pipian: Tiny Interface to CaboCha for R
- paithiov909/rjavacmecab: rJava Interface to CMeCab
- paithiov909/tangela: rJava Interface to atilika/kuromoji
- paithiov909/krikinton: rJava wrapper of Kintoki (a port of the CaboCha to Java) and Sudachi
Universal Dependenciesなら次が使えます。udpipeはC++実装のラッパー、spacyrはPythonバックエンドです。
- bnosac/udpipe: R package for Tokenization, Parts of Speech Tagging, Lemmatization and Dependency Parsing Based on the UDPipe Natural Language Processing Toolkit
- quanteda/spacyr: R wrapper to spaCy NLP
最近になってbnosacからBPE(Byte Pair Encoding)とsentencepieceのRラッパーがリリースされました。
- bnosac/tokenizers.bpe: R package for Byte Pair Encoding based on YouTokenToMe
- bnosac/sentencepiece: R package for Byte Pair Encoding / Unigram modelling based on Sentencepiece
Language Representations
アクティブに開発されていそうなものとして、このあたりのパッケージがあります。
- dselivanov/text2vec: Fast vectorization, topic modeling, distances and GloVe word embeddings in R.
- pommedeterresautee/fastrtext: R wrapper for fastText
- bnosac/ruimtehol: R package to Embed All the Things! using StarSpace
- bnosac/doc2vec: Distributed Representations of Sentences and Documents
- bnosac/golgotha: Contextualised Embeddings and Language Modelling using BERT and Friends using R
- jonathanbratt/RBERT: Implementation of BERT in R
セットアップ
normalize
は前処理用の秘伝のタレです。
library(tidymodels)
#> -- Attaching packages ------------------------------------------- tidymodels 0.1.2 --
#> √ broom 0.7.3 √ recipes 0.1.15
#> √ dials 0.0.9 √ rsample 0.0.8
#> √ dplyr 1.0.2 √ tibble 3.0.4
#> √ ggplot2 3.3.3 √ tidyr 1.1.2
#> √ infer 0.5.3 √ tune 0.1.2
#> √ modeldata 0.1.0 √ workflows 0.2.1
#> √ parsnip 0.1.4 √ yardstick 0.0.7
#> √ purrr 0.3.4
#> -- Conflicts ---------------------------------------------- tidymodels_conflicts() --
#> x purrr::discard() masks scales::discard()
#> x dplyr::filter() masks stats::filter()
#> x dplyr::lag() masks stats::lag()
#> x recipes::step() masks stats::step()
library(textrecipes)
library(zipangu)
library(tokenizers.bpe)
library(RcppMeCab)
library(fastrtext) ## Not on CRAN
library(ldccr) ## 自作パッケージ
#' Normalize text neologd-styled
#'
#' @param str Character vector.
#' @return Normalized text.
#' @import stringr
#' @importFrom zipangu str_conv_normalize
normalize <- function(str) {
str %>%
stringr::str_replace_all("\u2019", "\'") %>%
stringr::str_replace_all("\u201d", "\"") %>%
stringr::str_replace_all("[\u02d7\u058a\u2010\u2011\u2012\u2013\u2043\u207b\u208b\u2212]", "-") %>%
stringr::str_replace_all("[\ufe63\uff0d\uff70\u2014\u2015\u2500\u2501\u30fc]", enc2utf8("\u30fc")) %>%
stringr::str_replace_all("[~\u223c\u223e\u301c\u3030\uff5e]", "~") %>%
stringr::str_remove_all("[[:punct:]]+") %>%
stringr::str_remove_all("[[:blank:]]+") %>%
stringr::str_remove_all("[[:cntrl:]]+") %>%
zipangu::str_conv_normalize() %>%
return()
}
データの準備
livedoorニュースコーパスを使います。以下の9カテゴリです。
- トピックニュース
- Sports Watch
- ITライフハック
- 家電チャンネル
- MOVIE ENTER
- 独女通信
- エスマックス
- livedoor HOMME
- Peachy
パーサを書いたので、それでデータフレームにします。
data <- ldccr::parse_ldcc()
#> Parsing dokujo-tsushin...
#> Parsing it-life-hack...
#> Parsing kaden-channel...
#> Parsing livedoor-homme...
#> Parsing movie-enter...
#> Parsing peachy...
#> Parsing smax...
#> Parsing sports-watch...
#> Parsing topic-news...
#> Done.
この記事を書いた当初はRcppMeCab + Neologdでの形態素解析を試そうとして上手くいかず、rjavacmecabという自作パッケージで代用していました(動くけど非常に遅い)。以下のような感じです。
corpus_mecab <- data %>%
dplyr::sample_frac(.01) %>%
dplyr::mutate(category = as.factor(category)) %>%
dplyr::mutate(body = normalize(body)) %>%
tibble::rowid_to_column()
corpus_mecab <- corpus_mecab %>%
dplyr::group_by(rowid) %>%
dplyr::group_map(~
.x$body %>%
rjavacmecab::cmecab(opt = dic_opt, sep = "\t") %>%
rjavacmecab::prettify(sep = "\t") %>%
dplyr::pull(Original) %>%
paste(collapse = " ")) %>%
purrr::map_dfr(~ tibble::tibble(tokens = .)) %>%
dplyr::bind_cols(corpus_mecab)
その後、RcppMeCabを使う場合には次のような感じでできるのを確認しました。ただし、2021年1月現在CRANにあるバージョン(0.0.1.2)は未知語の処理にバグがあるようなのでここではソースを修正したものを使っています(後でPRを出します)。
corpus_mecab <- data %>%
dplyr::sample_frac(.01) %>% ## ここではあらかじめサンプルを減らしておく
dplyr::mutate(category = as.factor(category)) %>%
dplyr::mutate(body = normalize(body)) %>%
tibble::rowid_to_column()
corpus_mecab <- corpus_mecab %>%
dplyr::pull(body) %>%
RcppMeCab::posParallel(format = "data.frame") %>%
dplyr::mutate(doc_id = as.integer(doc_id)) %>% ## doc_idがcharacterで返ってくるためintに変換する
dplyr::group_by(doc_id) %>%
dplyr::mutate(tokens = paste(token, collapse = " ")) %>%
dplyr::select(doc_id, tokens) %>%
dplyr::left_join(corpus_mecab, by = c("doc_id" = "rowid"))
tokenizer.bpeでサブワード分割する場合。
corpus_bpe <- data %>%
dplyr::mutate(category = as.factor(category)) %>%
dplyr::mutate(body = normalize(body)) %>%
tibble::rowid_to_column()
token_model <- data %>%
dplyr::pull(body) %>%
tokenizers.bpe::bpe(vocab_size = 5000) ## equal to default
corpus_bpe <- corpus_bpe %>%
dplyr::pull(body) %>%
purrr::map_chr(~
tokenizers.bpe::bpe_encode(token_model, x = ., type = "subword") %>%
unlist() %>%
paste(collapse = " ")) %>%
purrr::map_dfr(~ tibble(tokens = .)) %>%
dplyr::bind_cols(corpus_bpe)
こういうデータになります。
corpus <- list(mecab = corpus_mecab, bpe = corpus_bpe) %>%
purrr::map(~ dplyr::glimpse(.)) %>%
purrr::map(~ rsample::initial_split(., p = .8))
#> Rows: 41,100
#> Columns: 7
#> Groups: doc_id [74]
#> $ doc_id <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
#> $ tokens <chr> "モップ 風 の クリーナー で 超 かわいい ソフト バンク BB が CRAFTHOLIC と の コラボ 商品 第 3 弾 ...
#> $ category <fct> smax, smax, smax, smax, smax, smax, smax, smax, smax, smax, smax,...
#> $ file_path <chr> "C:\\Users\\user\\AppData\\Local\\Temp\\RtmpKY2tNF/text/smax/smax...
#> $ source <chr> "http://news.livedoor.com/article/detail/6900354/", "http://news....
#> $ time_stamp <chr> "2012-08-29T15:55:00+0900", "2012-08-29T15:55:00+0900", "2012-08-...
#> $ body <chr> "モップ風のクリーナーで超かわいいソフトバンクBBがCRAFTHOLICとのコラボ商品第3弾CRAFTHOLICストラップ付きクリ...
#> Rows: 7,367
#> Columns: 7
#> $ tokens <chr> "<U+2581> 友 人 代表 の スピ ー チ 独女 はどう こ な している もう すぐ ジ ュー ン ブ ライ ド と 呼 ば れる 6...
#> $ rowid <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19...
#> $ category <fct> dokujo-tsushin, dokujo-tsushin, dokujo-tsushin, dokujo-tsushin, d...
#> $ file_path <chr> "C:\\Users\\user\\AppData\\Local\\Temp\\RtmpKY2tNF/text/dokujo-ts...
#> $ source <chr> "http://news.livedoor.com/article/detail/4778030/", "http://news....
#> $ time_stamp <chr> "2010-05-22T14:30:00+0900", "2010-05-21T14:30:00+0900", "2010-05-...
#> $ body <chr> "友人代表のスピーチ独女はどうこなしているもうすぐジューンブライドと呼ばれる6月独女の中には自分の式はまだなのに呼ばれてばかりとい...
モデルの学習1(FeatureHashing)
次のような関数でデータを分割します。
prep_corpus <- function(corpus, recipe) {
train <- recipe %>%
recipes::juice()
test <- recipe %>%
recipes::bake(rsample::testing(corpus))
return(list(train = train, test = test))
}
以下のレシピとモデルで学習します。ハッシュトリックを使っています。デフォルトだとパラメータはここに書いている感じになります。
model <- parsnip::boost_tree() %>%
parsnip::set_engine("xgboost") %>%
parsnip::set_mode("classification") %>%
parsnip::translate()
fit_corpus <- function(corpus, model) {
recipe <- recipes::recipe(
category ~ tokens,
data = rsample::training(corpus)
) %>%
textrecipes::step_tokenize(tokens) %>%
textrecipes::step_texthash(tokens) %>%
recipes::prep()
split <- prep_corpus(corpus, recipe)
fitted <- model %>%
parsnip::fit(category ~ ., data = split$train)
fitted %>%
predict(split$test) %>%
dplyr::bind_cols(split$test) %>%
yardstick::metrics(truth = category, estimate = .pred_class)
}
print(model)
#> Boosted Tree Model Specification (classification)
#>
#> Computational engine: xgboost
#>
#> Model fit template:
#> parsnip::xgb_train(x = missing_arg(), y = missing_arg(), nthread = 1,
#> verbose = 0)
fit
して、精度をみてみます(MeCab + Neologdのほうはさすがにサンプルが少なすぎたかもしれない)。
purrr::map(corpus, ~ fit_corpus(., model))
#> [18:54:01] WARNING: amalgamation/../src/learner.cc:1061: Starting in XGBoost 1.3.0, the default evaluation metric used with the objective 'multi:softprob' was changed from 'merror' to 'mlogloss'. Explicitly set eval_metric if you'd like to restore the old behavior.
#> [18:57:36] WARNING: amalgamation/../src/learner.cc:1061: Starting in XGBoost 1.3.0, the default evaluation metric used with the objective 'multi:softprob' was changed from 'merror' to 'mlogloss'. Explicitly set eval_metric if you'd like to restore the old behavior.
#> $mecab
#> # A tibble: 2 x 3
#> .metric .estimator .estimate
#> <chr> <chr> <dbl>
#> 1 accuracy multiclass 1
#> 2 kap multiclass 1
#>
#> $bpe
#> # A tibble: 2 x 3
#> .metric .estimator .estimate
#> <chr> <chr> <dbl>
#> 1 accuracy multiclass 0.897
#> 2 kap multiclass 0.884
モデルの学習2(fasttext)
BPEでサブワード分割した文書について、fasttextで埋め込みを得てから学習してみます。ここでは50次元のベクトルにします。
temp <- tempfile(fileext = ".txt")
readr::write_lines(
corpus_bpe$tokens,
file = temp
)
fastrtext::execute(c("skipgram", "-input", temp, "-output", "model", "-dim", 50L))
#>
Read 1M words
Read 2M words
Read 3M words
Read 4M words
Read 5M words
Read 5M words
#> Number of words: 4484
#> Number of labels: 0
#>
モデルの読み込み。
ft_model <- fastrtext::load_model("model.bin")
データフレームに整形します。
vocab <- fastrtext::get_dictionary(ft_model)
Encoding(vocab) <- "UTF-8" ## For Windows machine
embeddings <- ft_model %>%
fastrtext::get_word_vectors(vocab) %>%
as.data.frame() %>%
dplyr::bind_cols(tibble::tibble(vocab = vocab)) %>%
dplyr::select(vocab, everything())
remove(ft_model)
今度は次のようなレシピで学習します。上でやったのと同じように素直にやろうとすると手元の環境ではメモリが足りなかったので、ここではtextrecipes::step_tokenfilter
で語彙を削っています。
fit_corpus_b <- function(corpus, model) {
recipe <- recipes::recipe(
category ~ tokens,
data = rsample::training(corpus)
) %>%
textrecipes::step_tokenize(tokens) %>%
textrecipes::step_tokenfilter(tokens, min_times = 3L, max_tokens = 50L) %>%
textrecipes::step_word_embeddings(
tokens,
embeddings = tibble::as_tibble(embeddings)
) %>%
recipes::prep()
split <- prep_corpus(corpus, recipe)
fitted <- model %>%
parsnip::fit(category ~ ., data = split$train)
fitted %>%
predict(split$test) %>%
dplyr::bind_cols(split$test) %>%
yardstick::metrics(truth = category, estimate = .pred_class)
}
fit
します(なんか思ったほど精度がよくないのでどこか間違っているのかもしれない)。
fit_corpus_b(corpus$bpe, model)
#> # A tibble: 2 x 3
#> .metric .estimator .estimate
#> <chr> <chr> <dbl>
#> 1 accuracy multiclass 0.576
#> 2 kap multiclass 0.522
所感
livedoorニュースコーパスはそんなに大きなコーパスじゃないのでサクッとできてほしいのですが、textrecipesで埋め込みを扱うには手元の環境では不足なようでした(たぶん私が使っているPCが古いだけですが)。
このコーパスのカテゴリ分類はかなり易しいタスクであることが知られているので相性もあるのでしょうが、ハッシュトリックしてXGBoostに投入するだけで簡単によい精度の予測ができる点は気持ちよいです。bnosac/sentencepieceもtokenizer.bpeと同じノリで使えるようなので、サブワード分割でよければRでも簡単にできるとわかりました。
一方で、形態素解析については辞書を手軽に差し替えられて速い・実用的な実装が見つからないのが痛いです。分かち書きするだけなら結局mecabのコマンドを直接叩くほうが確実な気がします。
セッション情報
sessioninfo::session_info()
#> - Session info ------------------------------------------------------------------------
#> setting value
#> version R version 4.0.2 (2020-06-22)
#> os Windows 10 x64
#> system x86_64, mingw32
#> ui RStudio
#> language (EN)
#> collate Japanese_Japan.932
#> ctype Japanese_Japan.932
#> tz Asia/Tokyo
#> date 2021-02-04
#>
#> - Packages ----------------------------------------------------------------------------
#> ! package * version date lib
#> assertthat 0.2.1 2019-03-21 [1]
#> backports 1.2.0 2020-11-02 [1]
#> broom * 0.7.4 2021-01-29 [1]
#> class 7.3-17 2020-04-26 [2]
#> cli 2.3.0 2021-01-31 [1]
#> codetools 0.2-16 2018-12-24 [2]
#> colorspace 2.0-0 2020-11-11 [1]
#> crayon 1.4.0 2021-01-30 [1]
#> data.table 1.13.6 2020-12-30 [1]
#> DBI 1.1.1 2021-01-15 [1]
#> dials * 0.0.9 2020-09-16 [1]
#> DiceDesign 1.8-1 2019-07-31 [1]
#> digest 0.6.27 2020-10-24 [1]
#> dplyr * 1.0.3 2021-01-15 [1]
#> ellipsis 0.3.1 2020-05-15 [1]
#> evaluate 0.14 2019-05-28 [1]
#> fansi 0.4.2 2021-01-15 [1]
#> fastrtext * 0.3.4 2021-02-03 [1]
#> float 0.2-4 2020-04-22 [1]
#> foreach 1.5.1 2020-10-15 [1]
#> furrr 0.2.2 2021-01-29 [1]
#> future 1.21.0 2020-12-10 [1]
#> generics 0.1.0 2020-10-31 [1]
#> ggplot2 * 3.3.3 2020-12-30 [1]
#> globals 0.14.0 2020-11-22 [1]
#> glue 1.4.2 2020-08-27 [1]
#> gower 0.2.2 2020-06-23 [1]
#> GPfit 1.0-8 2019-02-08 [1]
#> gtable 0.3.0 2019-03-25 [1]
#> hms 1.0.0 2021-01-13 [1]
#> htmltools 0.5.1.1 2021-01-22 [1]
#> infer * 0.5.4 2021-01-13 [1]
#> ipred 0.9-9 2019-04-28 [1]
#> iterators 1.0.13 2020-10-15 [1]
#> knitr 1.31 2021-01-27 [1]
#> lattice 0.20-41 2020-04-02 [2]
#> lava 1.6.8.1 2020-11-04 [1]
#> ldccr * 0.0.2 2021-02-03 [1]
#> lgr 0.4.2 2021-01-10 [1]
#> lhs 1.1.1 2020-10-05 [1]
#> lifecycle 0.2.0 2020-03-06 [1]
#> listenv 0.8.0 2019-12-05 [1]
#> lubridate 1.7.9.2 2020-11-13 [1]
#> magrittr 2.0.1 2020-11-17 [1]
#> MASS 7.3-51.6 2020-04-26 [2]
#> Matrix 1.2-18 2019-11-27 [2]
#> mlapi 0.1.0 2017-12-17 [1]
#> modeldata * 0.1.0 2020-10-22 [1]
#> munsell 0.5.0 2018-06-12 [1]
#> nnet 7.3-14 2020-04-26 [2]
#> parallelly 1.23.0 2021-01-04 [1]
#> parsnip * 0.1.5 2021-01-19 [1]
#> pillar 1.4.7 2020-11-20 [1]
#> pkgconfig 2.0.3 2019-09-22 [1]
#> plyr 1.8.6 2020-03-03 [1]
#> pROC 1.17.0.1 2021-01-13 [1]
#> prodlim 2019.11.13 2019-11-17 [1]
#> purrr * 0.3.4 2020-04-17 [1]
#> R.cache 0.14.0 2019-12-06 [1]
#> R.methodsS3 1.8.1 2020-08-26 [1]
#> R.oo 1.24.0 2020-08-26 [1]
#> R.utils 2.10.1 2020-08-26 [1]
#> R6 2.5.0 2020-10-28 [1]
#> Rcpp 1.0.6 2021-01-15 [1]
#> RcppMeCab * 0.0.1.3-2 2021-02-04 [1]
#> D RcppParallel 5.0.2 2020-06-24 [1]
#> readr 1.4.0 2020-10-05 [1]
#> recipes * 0.1.15 2020-11-11 [1]
#> rematch2 2.1.2 2020-05-01 [1]
#> RhpcBLASctl 0.20-137 2020-05-17 [1]
#> rlang 0.4.10 2020-12-30 [1]
#> rmarkdown 2.6 2020-12-14 [1]
#> rpart 4.1-15 2019-04-12 [2]
#> rsample * 0.0.8 2020-09-23 [1]
#> rsparse 0.4.0 2020-04-01 [1]
#> rstudioapi 0.13 2020-11-12 [1]
#> scales * 1.1.1 2020-05-11 [1]
#> sessioninfo 1.1.1 2018-11-05 [1]
#> SnowballC 0.7.0 2020-04-01 [1]
#> stringi 1.5.3 2020-09-09 [1]
#> stringr 1.4.0 2019-02-10 [1]
#> styler 1.3.2 2020-02-23 [1]
#> survival 3.1-12 2020-04-10 [2]
#> text2vec 0.6 2020-02-18 [1]
#> textrecipes * 0.4.0 2020-11-12 [1]
#> tibble * 3.0.5 2021-01-15 [1]
#> tidymodels * 0.1.2 2020-11-22 [1]
#> tidyr * 1.1.2 2020-08-27 [1]
#> tidyselect 1.1.0 2020-05-11 [1]
#> timeDate 3043.102 2018-02-21 [1]
#> tokenizers 0.2.1 2018-03-29 [1]
#> tokenizers.bpe * 0.1.0 2019-08-02 [1]
#> tune * 0.1.2 2020-11-17 [1]
#> utf8 1.1.4 2018-05-24 [1]
#> vctrs 0.3.6 2020-12-17 [1]
#> withr 2.4.1 2021-01-26 [1]
#> workflows * 0.2.1 2020-10-08 [1]
#> xfun 0.20 2021-01-06 [1]
#> xgboost 1.3.2.1 2021-01-18 [1]
#> yaml 2.2.1 2020-02-01 [1]
#> yardstick * 0.0.7 2020-07-13 [1]
#> zipangu * 0.2.2 2021-02-01 [1]
#> source
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> Github (pommedeterresautee/fastrtext@b63c5de)
#> CRAN (R 4.0.0)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> Github (paithiov909/ldccr@4655ab1)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> local
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.0)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.0)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.0)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.3)
#> CRAN (R 4.0.0)
#> CRAN (R 4.0.2)
#> CRAN (R 4.0.2)
#>
#> [1] C:/Users/user/Documents/R/win-library/4.0
#> [2] C:/Program Files/R/R-4.0.2/library
#>
#> D -- DLL MD5 mismatch, broken installation.
Comments