京橋のバイオインフォマティシャンの日常

南国のビーチパラソルの下で、Rプログラムを打ってる日常を求めて、、Daily Life of Bioinformatician in Kyobashi of Osaka

【Rのジミ〜な小技シリーズ】データ解析の前処理で悩まされるデータ重複の問題を扱ってみた件

はじめに

本記事は、

skume.hatenablog.com

の続編である。

さて、これからデータ解析を始めようかという時に、まずやることは該当データのクオリティチェック(品質評価)だろう。

クオリティチェックと言っても、いろいろな方法・考え方があって、データによって様々である。

今回は、最も基本である、データ重複の問題を扱ってみる。

練習データの準備

X、Y、XY、Zという変数を作成してみる。

#変数の作成
X <- c("A", "B", "C", "D", "E")
Y <- c("G", "H", "A", "B", "I")
XY <- c(X, Y) 
Z <- data.frame(V1=c("A", "B", "C", "D", "D", "D"),
                V2=c(1, 5, 3, 6, 6, 7),
                stringsAsFactors = F)

ベクトル内で、データの重複があるかどうか?どう扱うか?

ベクトルデータ内の重複があるかどうかは、まずはtable()で確認する。

XY変数は、AとBが重複している。

table(XY)
#XY
#A B C D E G H I 
#2 2 1 1 1 1 1 1 

table(table(XY) == 1)
#FALSE  TRUE 
#    2     6 

一般的には、unique()を使って、ベクトル内の重複を除く。

unique()では、ベクトルの重複しない値・文字列を返してくれる

XY.u <- unique(XY)
XY.u
#[1] "A" "B" "C" "D" "E" "G" "H" "I"

table(XY.u)
#XY.u
#A B C D E G H I 
#1 1 1 1 1 1 1 1 

table(table(XY.u) == 1)
#TRUE 
#   8

次に、duplicated()を使って、ベクトル内の重複を除いてみる。

duplicated()は重複を判定する関数であり、 その逆(!)が重複を除いた結果を返すことになる。

!duplicated(XY)
#[1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE

XY.d <- XY[!duplicated(XY)]
XY.d

table(XY.d)
#XY.d
#A B C D E G H I 
#1 1 1 1 1 1 1 1 

table(table(XY.d) == 1)
#TRUE 
#   8 

2つのベクトル間で、データの重複があるかどうか?・重複をどう扱うか?

ここでは、intersect、setdiff、%in%あたりをやってみる。

#XとYに共通する項目
intersect(X, Y)
#[1] "A" "B"

X[X %in% Y]
#[1] "A" "B"

#Xのみに含まれる項目
setdiff(X, Y)
#[1] "C" "D" "E"

X[!c(X %in% Y)]
#[1] "C" "D" "E"

データフレーム内で、データの重複があるかどうか?・重複をどう扱うか?

unique()を使って、データフレームのデータ重複を除いてみる。

unique()でも出来ない事はない。

Z$V3 <- paste(Z$V1, ".", Z$V2, sep="")

Z.u <- Z[as.numeric(rownames(unique(Z["V3"]))),]
#  V1 V2  V3
#1  A  1 A.1
#2  B  5 B.5
#3  C  3 C.3
#4  D  6 D.6
#6  D  7 D.7

#あるいは
#or Z.u <- Z[rownames(unique(Z["V3"])),]

次に、duplicated()を使って、データフレームのデータ重複を除いてみる。

duplicated()では、複数列での重複をTRUE /FALSEで返してくれるので、これはなかなか良い。

Z.d1 <- Z[!duplicated(Z[,1:2]),]

Z.d1
#  V1 V2  V3
#1  A  1 A.1
#2  B  5 B.5
#3  C  3 C.3
#4  D  6 D.6
#6  D  7 D.7

#あるいは
Z.d2 <- Z[!duplicated(Z[,c("V1", "V2")]),]
Z.d2

まとめ

この記事 + α は毎回やる必要があるので、覚えておくと良い。

参考資料

a-habakiri.hateblo.jp

qiita.com

jojoshin.hatenablog.com

【Rのジミ〜な小技シリーズ】

skume.net

skume.net

skume.net

skume.net

skume.net

skume.net

skume.net

skume.net

skume.net

バーチャルスライドスキャナー画像(.ndpi)からオリジナルTIFFイメージを取り出す際のTips〜ギガバイトイメージの画像解析入門〜

はじめに

今回、バーチャルスライドスキャナー画像(.ndpi)の取り扱い方を取り上げる。

.ndpiという画像フォーマットは、浜松ホトニクス社が提供するHamamatsu formatの1つである。

NDPIファイルは「独自メタデータを持つシングルファイルTIFF-likeな形式」であり、一般的によく使われるTIFFとかPNGと比べて、なかなか扱いにくい形式である。

また、TIFF-like形式というのは実際、Compress TIFF 形式で格納されていて、ImageJではその形式に対応したプラグインを導入する必要がある。

NDPIToolsのセットアップ

NDPITools HPから、ndpi2tiff、ndpisplit、ImageJ pluginsをダウンロードして、セットアップしてみる*1

まず、Mac版wgetのセットアップは、以前の記事を参考のこと。

skume.hatenablog.com

また、Fiji/ImageJについては以下のURLでダウンロード・インストールしておく。

https://imagej.net/Fiji.html#Downloadsimagej.net

以下、MacOSX版とLINUX版でのセットアップについて概説する。

#MacOSX版
#Pkg installerのダウンロード
wget https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/download/ndpitools-1.8/macosx/ndpitools-1.8.pkg

#インストール
open ndpitools-1.8.pkg
rm -rf ndpitools-1.8.pkg
#あるいは
#ndpitools-1.8.pkgをダブルクリックして、インストールする。

#パスの確認
which ndpi2tiff
#/usr/local/bin/ndpi2tiff

which ndpisplit
#/usr/local/bin/ndpisplit 

#ImageJ pluginsのインストール
wget https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/download/ndpitools-1.7.2/NDPITools_.jar

#.jarファイルをFiji/ImageJのプラグインフォルダに移動させる
mv ./NDPITools_.jar /Applications/Fiji.app/plugins

一応、Linux版のセットアップについてもふれておく。

#Linux版のセットアップ
#ndpi2tiff
wget https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/download/ndpitools-1.8/lin64/ndpi2tiff
chmod a+x ndpi2tiff
sudo mv ndpi2tiff /usr/local/bin

#ndpisplit
wget https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/download/ndpitools-1.8/lin64/ndpisplit
chmod a+x ndpisplit
sudo mv ndpisplit /usr/local/bin

# プラグインの設定
wget https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/download/ndpitools-1.7.2/NDPITools_.jar
#Fiji/ImageJのプラグインフォルダに移動させる

NDPIテストファイルのダウンロード

次に、テストデータ(CMU-1.ndpi)をダウンロードして、実行例を概説する。

#フォルダ作成
mkdir test01

#フォルダ内に移動
cd test01

#テストデータのダウンロード
wget http://openslide.cs.cmu.edu/download/openslide-testdata/Hamamatsu/CMU-1.ndpi

ndpisplitコマンドを用いたNDPIファイルの展開

ndpisplitを使って、CMU-1.ndpiからオリジナルTIFFイメージを抽出する。

#(デフォルト: 全部出力、JPEG圧縮TIFFファイル出力)
ndpisplit CMU-1.ndpi

#メモリ4000MB制限、JPEG出力、x1.25の抽出、ログ出力`-K`
ndpisplit -m4000j75 -x1.25 -K CMU-1.ndpi

#メモリ4000MB制限、非圧縮出力、x5の抽出、ログ出力`-K`
ndpisplit -m4000n -x5 -K CMU-1.ndpi

Fiji/ImageJでのCompress TIFFのインポート&エクスポート

FijiでCompress TIFFを読み込むには、Pluginsメニュー > NDPITools > Open TIFF ...を選択して、出力したTIFFファイルを選択する。

CMU-1.ndpiイメージはこんな感じの画像。

次に、PNGファイルとしてエクスポートしてみる。

エクスポートしたい画像のウインドを選択した後に、Fileメニュー > Save As > PNG ...を選択して、画像を保存する。

ImageJマクロでの実行

(今後、作成予定)

まとめ

バーチャルスライド画像からのTIFF画像抽出をまとめてみた。

ただ、バーチャルスライド画像は数百MGとか1GB以上の画像データが多く、 あまりスペックが低いラップトップで扱うと、 PCがトブ時があるのでご注意あれ。

また今後、この画像解析についても扱っていきたい。

ImageJ & 画像解析に関する入門書

以下に、ImageJ関連の図書を列挙しておきます。

補足

Fiji/ImageJのPluginsを使った画像抽出

どうもPCに負荷がかかりそうなので、非推奨ではあるけども、 Fiji/ImageJのPluginsでも画像抽出は可能である。

Fiji PluginsでCompress TIFFを読み込むには、Pluginsメニュー > NDPITools > Custom extract to TIFF ...を選択して、NDPIファイルをを選択する。

非圧縮TIFF出力の設定は以下の通りである。

でOKを押すと、同フォルダ内にTIFFファイルが出力されるので、 その画像をFiji/ImageJのツールバーにドロップすれば、画像が開くはず。

もしJPEG圧縮TIFFファイルで出力した場合には、FijiでCompress TIFFを読み込むには、Pluginsメニュー > NDPITools > Open TIFF ...を選択して、出力したTIFFファイルを選択して開く。

参考資料

NDPITools

https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/www.imnc.in2p3.fr

OpenSlide - Hamamatsu format

openslide.org

ndpisplit リファレンス

https://www.imnc.in2p3.fr/pagesperso/deroulers/software/ndpitools/ndpisplit.htmlwww.imnc.in2p3.fr

Deroulers et al., Analyzing huge pathology images with open source software, Diagnostic Pathology 8:92 (2013).

diagnosticpathology.biomedcentral.com

*1:ndpi2tiffについては、用途的にもあまり使わないと思われる。

【R言語と形態素解析】R環境/reticulateで実行する、Python版Sudachi『SudachiPy』による日本語形態素解析

はじめに

SudachiPyは、 Java で書かれたオープンソースの日本語形態素解析器SudachiのPython版です。 SudachiPyは、形態素解析の無料ツールとして活用できます。

www.mlab.im.dendai.ac.jp

日本語形態素解析で有名なmecabと比べて後発の後発の形態素解析器で、 複数の分割単位、固有表現抽出などの特徴があります。

特に、GiNZA(spaCy)を使ってUD(単語単位の依存構造)解析したいときに利用できます*1

今回、R/RStudio上でのSudachiPyの実行例を概説します。Macターミナルでの実行もできます。

個人的には、RユーザーにとってPythonパッケージがR環境上で実行できると、いろいろとメリットが大きいと考えています*2

例の如く、HomeBrewでPythonの環境構築を行います。詳しくは、過去の記事を参照のこと。

https://skume.hatenablog.com/entry/2020/05/10/225341skume.hatenablog.com

実行環境

MacOSX 10.15.6
R version 4.0.2 (2020-06-22)
RStudio 1.3.1056
Python 3.8.5
pip 20.1.1 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)

SudachiPyのデフォルト・インストール

さて、ターミナルを起動して、SudachiPyをインストールします。

#sudachipyのインストール
pip install sudachipy

#辞書のインストール
pip install sudachidict_core

Sudachi 辞書 fullの設定

Sudachiでは、3種類の辞書が提供されています。

  • small: UniDicの語彙のみが含まれる。

  • core: 基本的な語彙を含む(デフォルト)。

  • full: その他の固有名詞が含まれる。

ここでは、Sudachi 辞書 full をインストールして、その辞書への切り替えをやってみます。

#辞書 full のインストール
pip install sudachidict_full

#辞書の切替
sudachipy link -t full

また、SudachiPyには、コマンドライン版とPython版があり、pipでどちらもインストールされます。

上記コマンドは、RStudioのターミナルタブからも実行できます。

また、もう面倒で、Rコンソール上でインストールしたい場合には、以下で通るはずです。

#sudachipyインストール
system("pip install sudachipy sudachidict_core sudachidict_full")

#辞書の切替
system("sudachipy link -t full")

R環境でのコマンドライン版sudachipyの実行

次に、コマンドライン版sudachipyの実行例を下記に示します。

Rのsystem()を使うと、ターミナルコマンドを実行できます。 また、" "内の文字列を、ターミナル上で実行することも可能です。

#sudachipyのヘルプ表示
system("sudachipy tokenize -h")
#(出力省略)

#Sudachiのデフォルト形態素解析
system('echo "外国人参政権" | sudachipy')

#外国人参政権    名詞,普通名詞,一般,*,*,*    外国人参政権
#EOS

#`-a`オプションで、すべての出力を表示させる
system('echo "外国人参政権" | sudachipy -a')
 
#外国人参政権    名詞,普通名詞,一般,*,*,*    外国人参政権  外国人参政権  ガイコクジンサンセイケン    0
#EOS

#もしR側に出力を返したい場合には、「intern=T」をいれる 
Res <- system('echo "外国人参政権" | sudachipy', intern=T)
Res

#[1] "外国人参政権\t名詞,普通名詞,一般,*,*,*\t外国人参政権"
#[2] "EOS"  

#Split A modeで形態素解析
system('echo "外国人参政権" | sudachipy -m A')

#外国    名詞,普通名詞,一般,*,*,*    外国
#人   接尾辞,名詞的,一般,*,*,*    人
#参政    名詞,普通名詞,一般,*,*,*    参政
#権   接尾辞,名詞的,一般,*,*,*    権
#EOS

Split modeについては、補足に記載しています。

続いて、Python版の実行方法についても概説します。

R環境でのPythonパッケージ版sudachipyの実行

HomeBrewでインストールしたPythonは、/usr/local/bin/pythonに入っています。

お使いの環境で、use_pythonのパスは変更しておきます。

それでは、Pythonパッケージ版sudachipyの実行例を下記に示します。

また、R環境上でのPython実行は、reticulateパッケージを使います。

#SudachiPyの設定
reticulate::use_python("/usr/local/bin/python", required =T)
sudachipy <- reticulate::import(module = "sudachipy")

#sudachipyのヘルプ表示
reticulate::py_help(sudachipy)

ここから、SudachiPyで形態素解析を実行してみます。

#tokenizerの作成
tokenizer_obj = sudachipy$dictionary$Dictionary()$create()
tokenizer_obj

#形態素解析の実行
text = '国家公務員'
m = tokenizer_obj$tokenize(text=text)[0]

#各出力結果
m$surface()
#[1] "国家公務員"

m$dictionary_form()
#[1] "国家公務員"

m$reading_form()
#[1] "コッカコウムイン"

m$part_of_speech()
#[1] "名詞"     "普通名詞" "一般"     "*"        "*"        "*"     

次に、Split modeのオプジェクトを設定して、 Splitモードの違いで、形態素解析の結果がどのように変わるかをみていきます。

#Split modeのオプジェクト設定
SplitA = sudachipy$tokenizer$Tokenizer$SplitMode$A
SplitB = sudachipy$tokenizer$Tokenizer$SplitMode$B
SplitC = sudachipy$tokenizer$Tokenizer$SplitMode$C

#Split mode Aの場合
tokenizer_obj$tokenize(text=text, mode=SplitA)[0]
#国家
tokenizer_obj$tokenize(text=text, mode=SplitA)[1]
#公務
tokenizer_obj$tokenize(text=text, mode=SplitA)[2]
#員

#Split mode Bの場合
tokenizer_obj$tokenize(text=text, mode=SplitB)[0]
#国家
tokenizer_obj$tokenize(text=text, mode=SplitB)[1]
#公務員

#Split mode Cの場合
tokenizer_obj$tokenize(text=text, mode=SplitC)[0]
#国家公務員

また、SudachiPyでは、標準的な日本語に補正してくれる、語彙のノーマライズ機能 (Ex. 附属 => 付属)もあるようです。

m1 = tokenizer_obj$tokenize(text="附属")[0]
m1$normalized_form()
#[1] "付属"

自作関数SudachiTokenizerRについて

Pythonパッケージ版SudachiをR環境で動かすのは若干面倒なんですが、実行挙動を逆手にとって関数を作成しました*3

これまでのコマンドが動作した環境が前提で、コマンドライン版とほぼ同出力となる関数を作成しました。以下が実行例です。

#スクリプト読み込み
source("https://gist.githubusercontent.com/kumeS/db75fdb0389f9a84846c58f5dcf302c1/raw/662d60b9c1d371577e40b3d1a311cd7d1b1de327/SudachiTokenizerR")

#実行
Res <- SudachiTokenizerR(text='国家公務員', mode=SplitA)
Res

#(出力結果)
#  語彙 品詞タグ01 品詞タグ02 品詞タグ03 品詞タグ04 品詞タグ05 品詞タグ06
#1 国家       名詞   普通名詞       一般          *          *          *
#2 公務       名詞   普通名詞       一般          *          *          *
#3   員     接尾辞     名詞的       一般          *          *          *

#system実行結果をR環境に返す場合
print(system('echo "国家公務員" | sudachipy -m A', intern=T))

#(出力結果)
#[1] "国家\t名詞,普通名詞,一般,*,*,*\t国家"
#[2] "公務\t名詞,普通名詞,一般,*,*,*\t公務"
#[3] "員\t接尾辞,名詞的,一般,*,*,*\t員"    
#[4] "EOS" 

まとめ

R環境で、Sudachi形態素解析が使えれば、自然言語処理やテキスト処理などの処理の幅も広がるはずです。

SudachiTokenizerRで、Pythonパッケージ版の形態素解析もR環境で少しは使いものになりそうです*4

補足

辞書の設定ファイル「sudachi.json」について

python3.10版SudachiPyのsudachi.jsonを開きます。

open /opt/homebrew/lib/python3.10/site-packages/sudachipy/resources/sudachi.json 

full辞書のsystem.dicは以下のフォルダパスにあります。

#sudachidict_fullのフォルダを開く
open /opt/homebrew/lib/python3.10/site-packages/sudachidict_full/resources 

以下の通り、sudachi.jsonを修正します。

"systemDict" : null,

↓↓↓

"systemDict" : "/opt/homebrew/lib/python3.10/site-packages/sudachidict_full/resources/system.dic",

github.com

Rはイチスタート、Pythonはゼロスタート

Rでは、1,2,3...と 1 からベクトル位置が始まりますが、Pythonや他言語では、0,1,2,3...と 0 からベクトル位置が始まるのが一般的です。

'"の使い分け

Rでは、"..."(ダブルクォーテーション囲い)は、文字列指定の際に使用します。

"..."内にもう一度、"..."を入れたい場合は、個人的な使い方としては、'..."..."...'というように、外側を'...'(シングルクォーテーション囲い)にして、内側を"..."と記載します*5

一部、'...'を使っているところもあるけども、R上ではだいたい同じ挙動となります。

Split mode について

英語原文より

Sudachi provides three modes of splitting. In A mode, texts are divided into the shortest units equivalent to the UniDic short unit. In C mode, it extracts named entities. In B mode, into the middle units.

日本語サイトより

次に、トークナイザーのモードを定義する必要があります。

モードは、トークナイザーがテキストを分割する方法を決定するために使用されます。

A :テキストは、UniDicショートユニットに相当する最短ユニットに分割されます

B :テキストをAとCの間の中間単位に分割します

C :名前付きエンティティを抽出します

Rコード: SudachiTokenizerR

gist.github.com

参考資料

pypi.org

github.com

ichi.pro

*1:https://qiita.com/hi-asano/items/aaf406db875f1c81530e

*2:Python言語の習得やPython環境、データ構造への慣れが特に不要になる。また、すでにRプログラミング中級者以上なら、もう1つインタプリンタ言語(低速言語)を習得するのはやはり非効率だと思うわけです。

*3:若干騙し騙し的な感じで、Pythonの実行エラーがR側でコマンド実行に使われない仕組みを活用しています。

*4:まだ発展途上だけど

*5:おそらくは、その逆でも動く