4 データセットの作成と加工

4.1 概要

このページでは

について解説します。

4.2 データの読み込み

調査や実験などで得たデータはテキストファイルやExcelファイルなど様々な形で保存されています。R でデータ分析を行うには、まずそれらのデータを R に読み込む必要があります。

データのファイル形式としてはテキストファイルやバイナリファイル、Excel や XML、SAS や SPSSのデータ、SQL などのデータベース、あるいは画像ファイルの場合もあるでしょう。R ではこれら様々なデータ形式を読み込むことが可能です。

本ページではテキストファイルとエクセルファイルの読み込み方法について解説します。

4.2.1 サンプルデータ

サンプルデータとして以下のものを使います。

各ファイルを右クリックから保存し、dataset という名前のフォルダを作ってそこに入れておいて下さい。
下図は job.txt ファイルの中身(一部)です。

 

このデータは datarium パッケージに含まれている jobsatisfaction データです。
このデータをテキストファイル(txt, csv, tsv)やエクセルファイル(xlsx)に保存したものです。

テキストファイルとは中身が文字だけのファイルのことです。拡張子は txt や csv や tsv など。
csv (comma-separated values): データをコンマ記号で区切ったテキストファイル。
tsv (tab-separated values): データをタブ記号で区切ったテキストファイル。

4.2.2 テキストファイルの読み込み

テキストファイルを読み込むには read.table() 関数を使います。
データフレームとしてファイルの内容が読み込まれます。

引数の意味は以下のようです。

  • file: 読み込むファイルのパス
  • header: 読み込むファイルの1行目が変数名の行なら TRUE にする
  • sep: 区切り文字(separator)は何か
  • stringAsFactors: 文字を要因型に変換する場合は TRUE、文字列型にする場合は FALSE

file 引数について、上記の例ではカレントディレクトリ(getwd() 命令を実行して表示される場所)に dataset というフォルダを作成し、そのフォルダ内に job.txt ファイルがある状態を想定しています。

header 引数について、このテキストファイルは一行目が変数名の行になっているので TRUE にします。最初の行からデータの中身が始まるファイルの場合には FALSE にします。

sep 引数について、区切り文字がタブの場合は sep = “\t” とします。

read.table() 関数には他にも様々な引数があります。詳しくは help を確認して下さい。

この例で使った job.txt、job.csv、job.tsv の3つのファイルは実質的に同じものです。
txt ファイルと csv ファイルは拡張子が異なるだけでファイルの中身は同一ですし、tsvファイルは区切り文字がコンマの代わりにタブが使われているだけです。
結果的に、read.table() 関数を使って読み込まれたデータ(データフレーム)はどのファイルを読み込んだ場合でも同一の内容になります。

4.2.3 Excel ファイルの読み込み

エクセルファイルを R に読み込む一つの方法は、エクセル上でファイルを txt や csv などテキストファイルとして出力し、それを上術の方法で読み込むことです。

エクセルファイルを直接読み込みたい場合はパッケージを使います。openxlsx、xlsx、XLConnect など、エクセルの読み込み用の R パッケージはいくつかありますが、openxlsx 以外のパッケージは Java のインストールも必要になるため、ここでは openxlsx を使うことにします。

まずはパッケージをインストールします。

パッケージを読み込みます。

read.xlsx() 関数を使ってエクセルファイルを読み込みます。

4.3 データフレームの操作

このセクションで使うデータを用意します。

library( datarium )

job = as.data.frame( jobsatisfaction )

str( job )
## 'data.frame':    58 obs. of  4 variables:
##  $ id             : Factor w/ 58 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
##  $ gender         : Factor w/ 2 levels "male","female": 1 1 1 1 1 1 1 1 1 1 ...
##  $ education_level: Factor w/ 3 levels "school","college",..: 1 1 1 1 1 1 1 1 1 2 ...
##  $ score          : num  5.51 5.65 5.07 5.51 5.94 5.8 5.22 5.36 4.78 6.01 ...

job
##    id gender education_level score
## 1   1   male          school  5.51
## 2   2   male          school  5.65
## 3   3   male          school  5.07
## 4   4   male          school  5.51
## 5   5   male          school  5.94
## 6   6   male          school  5.80
## 7   7   male          school  5.22
## 8   8   male          school  5.36
## 9   9   male          school  4.78
## 10 10   male         college  6.01
## 11 11   male         college  6.01
## 12 12   male         college  6.45
## 13 13   male         college  6.45
## 14 14   male         college  6.38
## 15 15   male         college  6.74
## 16 16   male         college  6.09
## 17 17   male         college  6.30
## 18 18   male         college  5.58
## 19 19   male      university  9.13
## 20 20   male      university  9.28
## 21 21   male      university  8.84
## 22 22   male      university  9.28
## 23 23   male      university 10.00
## 24 24   male      university 10.00
## 25 25   male      university  9.57
## 26 26   male      university  8.99
## 27 27   male      university  9.13
## 28 28   male      university  8.70
## 29 29 female          school  5.80
## 30 30 female          school  5.94
## 31 31 female          school  5.22
## 32 32 female          school  5.65
## 33 33 female          school  6.38
## 34 34 female          school  6.38
## 35 35 female          school  6.09
## 36 36 female          school  5.51
## 37 37 female          school  5.51
## 38 38 female          school  4.93
## 39 39 female         college  6.52
## 40 40 female         college  6.67
## 41 41 female         college  5.94
## 42 42 female         college  6.38
## 43 43 female         college  7.10
## 44 44 female         college  7.10
## 45 45 female         college  6.81
## 46 46 female         college  6.23
## 47 47 female         college  6.23
## 48 48 female         college  5.65
## 49 49 female      university  8.26
## 50 50 female      university  8.41
## 51 51 female      university  9.13
## 52 52 female      university  9.57
## 53 53 female      university  9.42
## 54 54 female      university  8.84
## 55 55 female      university  8.55
## 56 56 female      university  7.97
## 57 57 female      university  6.52
## 58 58 female      university  7.39

job は 58 行・4 列のデータフレームです。

4.3.1 角括弧を用いたデータの抽出

データフレーム変数の角括弧内にひとつのインデックス(整数値または文字列)を入れると、その番号(名前)の列のみからなるデータフレームが得られます。

角括弧内にふたつのインデックスを入れると、その行・列に該当する値が得られます。

この時、インデックスにベクトルを使えば、複数行・複数列のデータが得られます。

上の例では、指定した列が1つだけだと返り値はベクトルですが、列が2つ以上の場合は返り値はデータフレームになることに注意してください。

返り値をデータフレームにしたい場合は引数に drop = FALSE を加えます。

2つのインデックスのうち片方を空にすると「全て」を意味するようになります。

4.3.2 条件に合う列の抽出

job データフレームから、男性の score のみを取り出したいとします。
男性のデータが 1 行目から 28 行目までだと知っていれば、これは以下のようにできます。

ただし、行の範囲がいつでも簡単に分かるわけではありません。例えば学歴が大学である行を抽出したい場合などは、該当する行が全て連続した場所にあるわけではなく探すのが面倒になります。

条件に一致する行を自動で見つけるには == 演算子を使います。

以下のような式を実行すると、job の各行がその条件に合致するかを示す論理値型のベクトルが得られます。

この論理値ベクトルをインデックスとして使うと、条件に一致した行が抽出できます。

素晴らしいですね。

ちなみに、コンマを消した以下の命令はエラーになります。

なぜエラーかというと、最初に説明したように、角括弧内に引数をひとつだけ入れた場合は抽出する列を指定していることになります。job は 4 つの列を持ったデータフレームなのに対し、角括弧内のベクトルの長さは 58 で、job が持つ列の数をオーバーしてしまっています。エラーメッセージはそのことを言っています。

4.3.4 $ 記法を使ったベクトルの抽出

データフレームでは $ 記号を使うと特定の列をベクトルとして取り出せます。

== 演算子を使った式を使えば、条件に一致した値のみを抽出できます。

最初に説明した方法と比べてみます。以下のそれぞれは同じ結果になります。

$ 記号を使った場合でも & を使った複数条件のマッチングが可能です。

4.3.5 subset() 関数を用いたデータフレームの抽出

ここまで、条件に一致する行の抽出を角括弧を使って行う方法を説明してきました。
実は、データフレームの条件マッチングを行うための別の(そして便利な)方法があります。

subset() 関数を使うとデータフレームから特定の行や列の抽出ができます。
subset( x, subset, select ) という引数を持ちます。
第1引数は処理したいデータフレームです。

subset 引数

subset 引数には抽出したい行の条件式を入れます。

%in% 演算子を使った例。

> 演算子を使った例。

subset 引数に入れる条件式においては $ 記号は使う必要はありません。つまり、
subset( job, subset = job$score > 9.5 )
といった書き方をする必要はありません(そう書いてもエラーにはならず同じ結果が得られますが)。
列の名前だけを書けば良いので、スクリプトが書きやすくまた見やすくなるメリットがあります。

select 引数

select 引数を使うと特定の列を抽出できます。

便利な記法として、マイナス記号を使うことで特定の列の除外を行うことができます。

データフレームに不要な列がありそれを捨てたい場合などに便利です。

特定の列をデータフレームから削除したい場合は列に NULL を代入する方法もあります。

4.3.8 結合

複数のデータフレームを結合する方法について説明します。
横方向の結合および縦方向の結合があります。

4.3.8.1 横方向の結合

例として以下のような df1 と df2 という2つのデータフレームがあったとします。

cbind() 関数を使ってこれらを結合できます。

この時、df1 と df2 の行数が同じである必要があります(同じでない場合はエラーになる)。

異なる行数のデータフレームを横方向に結合したい場合は rowr パッケージの cbind.fill() 関数を使います。