エクセルシートやcsvファイルにまとめた数値データはエクセル上で関数を使うなどして前処理してしまうことが多いですが、エクセル上の操作は記録の残らないマウス操作に依存するため、再現性がまったくありません。再現性を確保するため、可能な限りR上で前処理を行うことを強くお勧めします。
以下の内容は基本操作のごく一部です。ほとんどすべての情報は、以下のサイトとその内容をまとめた書籍に掲載されていますので自習することができます。
自宅PCでこの実習用で使っているファイルを保存してるフォルダ内に、今週用のフォルダを英数字のみを用いて作成してください。たとえば phyto2020 などの名前がいいでしょう。フォルダ名の中間にスペースを入れるのは厳禁です(たとえば、"phyto 2020"はダメ)。
そのフォルダに以下の3つのファイルをダウンロードしてください。
[2-i] 左クイックによってファイルをウェブブラウザにそのまま表示する
[2-ii] 左上角のダウンロードボタンを押す。
[2-iii] ダウンロード先を指定する画面が出たら1)で作成したフォルダ内に保存する。ダウンロード先を訊かれなかったら「ダウンロード」フォルダにダウンロードされている可能性が一番高いので、ダウンロードフォルダから1)で作ったフォルダ内にファイル移動する。
自分のコンピュータ上のRStudioまたはRを使っている人は、以下の説明に従って作業をします。RStudio Cloudを使っている人はここを飛ばして3-B)に進むこと。
RStudio利用の場合
[3-A-RS-i] RStudio利用者は、Rstudioを起動し、ツールバーからFile > New File > R Script を順にたどることによって新規Rスクリプトを作成する。
[3-A-RS-ii] スクリプトの一行目に以下のコメントを書く。T*****の部分は学籍番号を追加する。
#For 20200611 phytoplankton diversity analysis T*****
[3-A-RS-iii] キーボードショットカットの「Ctrl + S (マックの場合はCommand+S)」を押してファイルを保存する。このとき必ず1)で作成したフォルダ内に保存する。ファイル名は"phyto_diversity_2020_t*****.R"とすること(t****の部分は学籍番号)。
R直接利用の場合
[3-A-RN-i] Rを直接利用する人は、Rを起動し、 ツールバーからファイル>新しいスクリプト、を順にたどることによって新規Rスクリプトを作成する。
[3-A-RN-ii] スクリプトの一行目に以下のコメントを書く。T*****の部分は学籍番号を追加する。
#For 20200611 phytoplankton diversity analysis T*****
[3-A-RN-iii] キーボードショットカットの「Ctrl + S (マックの場合はCommand+S)」を押してファイルを保存する。このとき必ず1)で作成したフォルダ内に保存する。ファイル名は"phyto_diversity_2020_t*****.R"とすること(t****の部分は学籍番号)。
自分のコンピュータ上のRStudioまたはRを使っている人は、ここは飛ばして4)に進みます。RStudio Cloudを使っている人はここの説明通りに作業をします。
[3-B-RC-i] RStudio Cloud(https://rstudio.cloud/ )にログインする。
[3-B-RC-ii] 下の画面キャプチャを参考に新規プロジェクトを作成する。New Projectが作成されるまで時間がかかるので辛抱強く待つましょう。
New Projectが作られた直後はプロジェクトに名前がついていないので、下図にあるように "Untitled Project" の部分をクリックして名前を付けましょう。たとえば、"phyto2020"などがいいでしょう。
[3-B-RC-iii] 上の画面で言うと、右下のFiles, Plots, Packages等のタブの直下の「Upload」のボタンをクリックして、2)で自分のPCに保存した3つのファイルをアップロードします。アップロードがうまくいくとFilesのところに下のように表示されるはずです。
[3-B-RC-iv] はい、まだ終わりではありません。新規Rスクリプトを作成する必要があります。3-A)の「RStudio利用の場合」の[3-A-RS-i], [3-A-RS-ii], [3-A-RS-iii]と同じ作業をRStudio Cloud上でやってください。
[4-i] データの取り込みにおいては、まず「作業ディレクトリ(Working Directory)」を適切に指定しないとデータをRの上に取り込むことができません。自分のコンピュータ上のRStudioまたはRStudio Cloudを利用している場合は、「超重要情報」のところに載っている方法で、作業ディレクトリを指定してください。R単体利用の人は、「R-tips」という解説サイトの「06. 作業ディレクトリの変更」に載っている方法で、作業ディレクトリを指定してください。
[4-ii] それでは「2)データファイルのダウンロード」の部分の3つのcsvファイルを、それぞれ異なるデータフレームに読み込んで保存します。
上の二つのデータファイルを、それぞれ異なるデータフレームに保存してみます。
#load the data sets
data_2018 <- read.csv("data2018.csv", header=TRUE)
data_apr2019 <- read.csv("apr2019.csv", header=TRUE)
data_may2019 <- read.csv("may2019.csv", header=TRUE)
ここらへんで分からなくなる人が多いと思いますが、data_2018, data_apr2019, data_may2019というのは、Rの中でデータを加工したり計算に使ったりするためにデータを保存しておくハコ(オブジェクト)で、データフレームという形式のものです。data_2018というデータフレームの名前を使う(スクリプトに書き込む)ことによって、そのデータフレーム内のデータにアクセスできるようになります。それに対しdata2018.csvはPC上に保存されているファイルで、そのファイルの名前です。PC上からならどこからでもアクセスできるファイルと、Rのスクリプト上だけでアクセス可能なデータフレームを混同しないように注意してください。ファイルにアクセスするにはファイル名を指定する一方、R上のオブジェクトの一つのタイプであるデータフレームにアクセスにするにはデータフレームの名前を指定します。
[4-i]の説明をちゃんと読みましたか? それを読んで再度挑戦してください。
それでもだめなら、以下のトラブルシューティングを参考にしてミスの原因を探してください。
それでもうまくいかないときは質問してください。
データフレームの中身をチェックしてみると、植物プランクトンのタイプ(green, diatomなど)と種名(species)と個体数(群体数)(abundance = 細胞数もしくは群体数)の一覧であることが分かります。
View(data_2018)
#Check the part of the data set
data_2018$type
View()関数を使うとデータの中身がすべて見れる一方、データフレーム名の後に$マークを追加して列名を指定すると特定の列の情報だけが表示されます。RstudioのRエディターでは、data_2018$
まで書き込むとそれ以降の候補を自動表示してくれるので便利です。
あるいは、以下のようにすると各行(1行目)、各列(一列目)、特定の行-列(3行め、2列め)の値にそれぞれアクセスできます。
#access to sub-data
data_2018[1, ]
data_2018[, 1]
data_2018[3,2]
つぎのセクションではデータの抽出と結合を行いますが、その前にdata_2018, data_apr2019, data_may2019
の中身のデータを説明します。
data_2018の一列目をみると、type, species, cells0924no1, cells0924no2, cells1004no1, cells1004no2, cells1004no3, cells1025no1, cells1025no2となっています。type列には, green, cyano, diatom, motileの4種類のグループ分けが書いてあり、それぞれ、緑藻、シアノバクテリア(藍藻)、珪藻、動くタイプ(渦鞭毛藻やミドリムシなど)です。speciesには文字通り種名が書かれており、それ以降の列は、2018年9月24日のサンプルが2繰り返し(no1, no2)、2018年10月4日のサンプルが3繰り返し(no1, no2, no3)、2018年10月25日のサンプルが2繰り返し(no1, no2)となっています。このようにこの実習では、植物プランクトン群集の組成について顕微鏡を用いた過去の計数データを用いていきます。
同様に、data_apr2019, data_may2019はそれぞれ、2019年4月25日の5繰り返しサンプル、2019年5月20日の5繰り返しサンプルの計数結果が格納されています。
まとめ
次に、3つのデータフレームを結合して1つにまとめたいと思います。というのは、2018年の9月から2019年5月までの植物プランクトン組成を比較するときにデータの扱いが簡単になるからです。
[2-i] data_2018とそれ以外の二つのデータフレームで列名のつけ方に一貫性がないので、data_2018の方の列名を他に合わせて変更します。colnames()という関数でデータフレームの列名にアクセスできるので、それの3番目から9番目まで[3:9]を変更します。こういう作業は地味ですがフォーマットをそろえるという重要なステップなのでおざなりにはできません。
#change column names
colnames(data_2018)[3:9]<-c("cells0924a","cells0924b","cells1004a", "cells1004b","cells1004c", "cells1025a", "cells1025b")
[2-ii] 次にmerge()という関数をつかって、データフレームの列名が共通部分(type, species)を残しながら結合します。結合は二つのデータフレーム間でしかできないので、2段階に分けてやります。まずは、2019年の4月と5月のものを以下のスクリプトで結合(マージ)します。
#merge
data_2019 <- merge(data_apr2019, data_may2019, all=T)
上のスクリプトの意味は、merge()という関数を使って二つのデータフレーム(data_apr2019, data_may2019)を結合し,その結果を新たなデータフレーム(data_2019)に( "<-"という記号を使って)格納する、ということです。
次にdata_2019と上でマージの結果作った新しいデータフレームdata_2019とdata_2018を結合しましょう。
data_all <- merge(data_2018, data_2019, all=T)
[2-iii] View()関数を使って新しいデータフレームの中身を確認みると、サンプル間で共通していないspeciesの部分には、欠損データ(NA)が挿入されていることが分かります。たとえば、一行目のcyano, Anabaena affinisのところではcells0425c列などにNAが挿入されているのがわかるでしょう。
View(data_all)
ここまでの作業ができて何がうれしいかというと、非常に簡単なスクリプトで、レパートリーの異なる集計表を統合できるということなのです。もっと具体的に言うと、複数の時期に植物プランクトン群集の種組成の集計リストを作ることを想定すると、当然サンプリングする時期によって出現する種は異なるので、集計リストの種のレパートリー(集計表のspeciesのところに出てくる種の一覧)はサンプリングごとに当然変わってきてしまいます。つまり、出現しない種については個体数ゼロとして記録されるわけではなく、出現しなかった種は種のレパートリーには含まれません。集計する前から「すべての」種が載った集計表を作ってそれに実際に出現した種の個体数(細胞数、群体数)を書き込んでいくのでない限り、種のレパートリーが異なる集計表をたとえばエクセル上で単純にコピペで統合することは容易ではありません。merge()関数を使うと、簡単に出現しなかった部分については欠損値(NA)を自動で挿入してくれるので、勝手に統一した種のレパートリー表が作れてしまうのです。
[2-vi] 上で解説した通り、merge()関数は自動で集計表を整理してくれるわけですが、挿入されたNAをそのまま放置すると、NAは当然数字ではないので後々の統計解析の時のエラーの下になります。NAというのは、観測されなかった、すなわち個体数がゼロで会った部分に挿入されているわけですから、NAを全部ゼロに変えてしまえばいいわけです。
これらの作業をするには下のたった一行のスクリプトを実行すればいいだけなのですが、その内容を説明しましょう。is.na()という関数はインプットのオブジェクト(データフレームやベクトル等)の各要素がNAかどうかを判定して、NAなら真(TRUE)、NAでないなら偽(FALSE)を返す関数です。これをデータフレーム名[]の中に埋め込むと、データフレームの要素のうちTRUEの要素だけにアクセスすることができます。そして、そのアクセスされた要素にゼロを代入する(<- 0)という意味になっているため、データフレームの要素のうち値がNAだった要素がすべてゼロに置き換わります。
#convert all NA to zero
data_all[is.na(data_all)]<-0
最後に一連の作業がうまくいったか、data_allの中身をもう一度View()関数を使って確認してみましょう。NAがなくなっていれば成功です。
View(data_all)
2)までのデータの前処理を終えたところで、植物プランクトン群集の多様性解析に用いる「生データ(raw data)」が整理されました。 ここでは、もう1ステップ前処理を進めて、次の解析の準備をしていきます。
[3-i] 種だけのデータにまとめる
種レベルに注目して統計解析をするために、Typeの情報は取り除いてしまいましょう。[,c(-1)]の部分は、一列目を取りのぞくという意味で、<-を使って新しいデータフレームspecies_biwa_dataに格納しなおします。上書きせずに新しいデータフレームを用意している理由は、あとでType情報を別の解析に使うためです。うまくいったか、View()関数を使って確かめておきましょう。
#remove type data
species_biwa_data <- data_all[,c(-1)]
View(species_biwa_data)
[3-ii] 行名を変えてデータを修正
種のリストのデータフレーム(species_biwa_data)が完成しました。これに少し修正を加えます。まず、データフレームの列の一部となっている種名のリストを行(row)の名前にコピーします。
#copy species name to row names
rownames(species_biwa_data) <- species_biwa_data$species
これにより種名をデータフレームの要素として維持する必要はなくなったので、種名が保存されている一列目は削除します。
species_biwa_data <- species_biwa_data[,-1]
これをすると何がうれしいかというと、データフレームの要素自体がすべて数字になったので数字を扱う統計解析の時に無用なエラーを避けることができるところです。
[3-iii] 行と列を入れ替える
さらに、このデータフレームでは表の縦方向(行方向)に種が並んでおり、表の横方向(列方向)に異なるサンプルの計数結果が並んでいる形になっています。ここでは、今後の統計解析の準備として、この縦と横の並びを逆転させます。表の横と縦を並び替える作業は、線形代数の用語で転置(transpose)といい(日本語と英語でイニシャルがともにTなのは偶然です)、R上では簡単にt()という関数でできます。ついでに単に転置するとデータフレームでなくなってしまうのでas.data.frameという関数も同時に使います。これについては上書きします。
#transpose
species_biwa_data <- as.data.frame(t(species_biwa_data))
View(species_biwa_data)
[4-i] Typeごとに個体数を集計しTypeごとのデータだけにまとめる(発展的内容)
aggregate()という関数を使うと指定した列の情報を用いてデータを集計することができます。今回のプランクトンのデータには、各種にType (緑藻=green、珪藻=diatom、藍藻=cyano、鞭毛等を持ち移動性のもの=motile)が割り当てられています。このTypeごとに合計個体数を自動で計算することが可能です。
ここでは、Type情報が残っているデータフレームdata_allをもう一度使います。以下のスクリプトで引数の一つ目xはどの列のデータを集計に使うかを列名によって指定し、次の引数byは何を基準に集計するかを指定し、最後の引数FUNは集計の仕方の関数(FUNction)を指定しています。引数xにはすべての3~19列を指定(colnames(data_all)[3:19])を指定、引数FUNには合計を計算するsumを指定します。
#data aggregation is possible
aggregate(x=data_all[colnames(data_all)[3:19]], by=list(data_all$type),FUN=sum)
その結果は次のキャプチャ画像のようににコンソール(console)に表示されるはずです。
このままでは、コンソールに表示されているだけで、集計の結果は保存されていませんから、改めて新しいデータフレームを用意して格納しましょう。
type_composition<-aggregate(x=data_all[colnames(data_all)[3:19]], by=list(data_all$type),FUN=sum)
class(type_composition) #確かにデータフレームになっていることを確認
[4-ii] 行名を変えてデータを修正
[4-iii] 行と列を入れ替える
[自分で考えてコードを書く] それでは、上の3-ii)と3-iii)の処理の仕方を参考に、行名を変え、数字以外の列のデータを削除し、行と列を入れ替えるスクリプトを自分で書いて、type_compositionに上書きしましょう。View()関数を使ってこのデータフレームを表示した時に左の図のようになったら成功です。
ここでひと段落なのですが、上のようなデータをコピーしたり縦横を変えたりしていると、データの種類(数字numericか文字characterか要因factorか、など)が勝手に変わってしまうことがあります。一番注意しないといけないのは、見た目は数字のままなのにcharacterかfactorとしてRに認識されてしまう場合です。こうすると、数字に対して行う計算や統計などがうまくいきません。したがって、このようなエラーを防ぐためにclass関数を使ってデータの種類をチェックします。class(species_biwa_data[1,1])
の結果がnumericでないと困ります。
#check class
class(species_biwa_data)
class(species_biwa_data[1,1])