Data structures in R (Japanese ver)

## Settings for RMarkdown http://yihui.name/knitr/options#chunk_options
opts_chunk$set(comment = "", warning = FALSE, message = FALSE, tidy = FALSE, 
    echo = TRUE, fig.width = 10, fig.height = 8)
options(width = 116, scipen = 10)
## なかなかわかりにくいRで用いられるデータ形式について解説
## データフレームから始まって他の形式を解説します。

# 使い方
# この記載をすべてコピーして手元のRのエディタに貼付ける。
# Windows版では左上 [ファイル] → [新しいスクリプト]でエディタ。
# Mac版では真っ白い紙の形のアイコンでエディタ。
# 実行する行、あるいは範囲を選択して
# WindowsであればCtrl+R、MacであればCommand+Returnで実行。



#################### data.frame ####################
## 一番使うのはデータフレームです。
## Rのデモデータもほとんどデータフレームです。

## デモデータを読み込んでみます。
## 標準付属のdatasetsというパッケージのデータセット一覧
data(package="datasets")
## 一画面に収まるtreesというのをdata()で読み込みます。
data(trees)

## そのまま trees で実行すると中身が表示されます。
## 31本の桜の木のGirth直径(inch), Height高さ(feet), Volume体積(feet^3)
## というデータ。行がそれぞれの木に対応。列がそれぞれ変数になります。
## 31行、3列(行番号も入れると4列)のデータが表示されたのがみえますか。
trees
   Girth Height Volume
1    8.3     70   10.3
2    8.6     65   10.3
3    8.8     63   10.2
4   10.5     72   16.4
5   10.7     81   18.8
6   10.8     83   19.7
7   11.0     66   15.6
8   11.0     75   18.2
9   11.1     80   22.6
10  11.2     75   19.9
11  11.3     79   24.2
12  11.4     76   21.0
13  11.4     76   21.4
14  11.7     69   21.3
15  12.0     75   19.1
16  12.9     74   22.2
17  12.9     85   33.8
18  13.3     86   27.4
19  13.7     71   25.7
20  13.8     64   24.9
21  14.0     78   34.5
22  14.2     80   31.7
23  14.5     74   36.3
24  16.0     72   38.3
25  16.3     77   42.6
26  17.3     81   55.4
27  17.5     82   55.7
28  17.9     80   58.3
29  18.0     80   51.5
30  18.0     80   51.0
31  20.6     87   77.0

## class()を使うとデータ構造が表示されます。data.frameです。
class(trees)
[1] "data.frame"

## STRucture()関数の方がOBServation数、変数の数、変数の名前
## それぞれの変数の型(この場合は3ついずれもNUMeric 数値)もでて有用かも。
str(trees)
'data.frame':   31 obs. of  3 variables:
 $ Girth : num  8.3 8.6 8.8 10.5 10.7 10.8 11 11 11.1 11.2 ...
 $ Height: num  70 65 63 72 81 83 66 75 80 75 ...
 $ Volume: num  10.3 10.3 10.2 16.4 18.8 19.7 15.6 18.2 22.6 19.9 ...


## read.csv()を用いて外部から読み込んだデータもdata.frameになります。
## 基本的にはdata.frameさえ使えればだいたいよいのですが、以下詳しい解説。




#################### vector ####################
## 一番シンプルなのは一つだけ値が入っているobjectです。
## 一つの値を入れるときはそのまま <- でok。文字列ならば""でくくる。
NUMBER <- 42
NAME <- "吉田"

## 呼び出すときはそのobjectの名前を打ち込むと中身が表示されます。
NUMBER
[1] 42
NAME
[1] "吉田"

## 構造は何でしょう?それぞれNUMeric数値とCHaRacter文字列と表示されています。
## それぞれnemeric vector/数値ベクトルとcharacter vector/文字列ベクトルと
## いうものにあたります。
## ベクトルとは値を一直線に並べたものですが、この場合は値が一つだけで、
## 特別にscalarと呼ばれることもあります。
str(NUMBER)
 num 42
str(NAME)
 chr "吉田"

## 値を一直線上に束ねたベクトルを作るにはCombine()という関数を使います。
## 数値を一直線に束ねてみます。
VECTOR <- c(1,5,7,15)
VECTOR
[1]  1  5  7 15

## 構造チェックのSTRucture()を使うとNUMeric数値の表示です。
## 値が四つになっただけでさっきの NUMBER と同じnumです。
str(VECTOR)
 num [1:4] 1 5 7 15
str(NUMBER)
 num 42

## 文字列を束ねてみます。
VECTOR2 <- c("吉田一郎", "吉田二郎", "吉田三郎", "吉田四郎")
VECTOR2
[1] "吉田一郎" "吉田二郎" "吉田三郎" "吉田四郎"

## 構造チェックのSTRucture()を使うとCHaRacter文字列の表示です。
## 値が四つになっただけでさっきの NAME と同じchrです。
str(VECTOR2)
 chr [1:4] "吉田一郎" "吉田二郎" "吉田三郎" "吉田四郎"
str(NAME)
 chr "吉田"

## vectorの特徴としてすべての値が同じ形式、つまり、数値なら数値、
## 文字列なら文字列である必要がある、ということがあげられます。
## では違う種類を並べるとどうでしょう?
## むりやりc()をつかって数値ベクトルと文字列ベクトルをさらに並べます。
VECTOR.COMBINED <- c(VECTOR, VECTOR2)

## 一直線に並びましたが、数値に""がついています。
## これはすべて文字列として扱われていることをしめします。
VECTOR.COMBINED
[1] "1"        "5"        "7"        "15"       "吉田一郎" "吉田二郎" "吉田三郎" "吉田四郎"

## STRucture()で形式をチェクするとCHaRacter文字列として扱われています。
## 数値と文字列を無理矢理組み合わせるとすべて文字列になります。
str(VECTOR.COMBINED)
 chr [1:8] "1" "5" "7" "15" "吉田一郎" "吉田二郎" "吉田三郎" "吉田四郎"

## なにが違うかというと、数値はまとめて計算できます。3をかけてみます。
VECTOR
[1]  1  5  7 15
VECTOR * 3
[1]  3 15 21 45

## 文字列は計算ができません。前半の"1" "5" "7" "15"も計算できませんでした。
VECTOR.COMBINED
[1] "1"        "5"        "7"        "15"       "吉田一郎" "吉田二郎" "吉田三郎" "吉田四郎"
VECTOR.COMBINED * 3
Error: non-numeric argument to binary operator





#################### 次にmatrixです。 ####################
## 一本のvectorベクトルを畳んだものがmatrix行列になります。

## まず長めのベクトルを作ってみます。1:20は1から20という意味です。
1:20
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
LONG.VECTOR <- 1:20

## 1から20までの20の値を持つ一直線のベクトルができました。
LONG.VECTOR
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

## データ形式をみるとINTeger整数となっています。
## どうも1:20という省略形式を使うと整数しか出てこないのでintになるようです。
str(LONG.VECTOR)
 int [1:20] 1 2 3 4 5 6 7 8 9 10 ...

## これを畳み込んでmatrix行列にしてみます。Number of COLumnsが5です。
MATRIX <- matrix(data=LONG.VECTOR, ncol=5)

## ベクトルが畳まれて5列、4行の行列になったのがわかりますか。
## 1列目から1,2,3,4というふうに縦に畳まれています。
MATRIX
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20


## 直感的に分かりにくいので横に畳むにはBY ROW行方向というオプションを使います。
MATRIX2 <- matrix(data=LONG.VECTOR, ncol=5, byrow=TRUE)

## 今度は横方向に畳まれたのがわかりますか。
MATRIX2
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
[4,]   16   17   18   19   20

## データ形式をチェックします。class()を使うとmatrixであることがわかります。
class(MATRIX2)
[1] "matrix"

## STRucture()はINTeger整数としか教えてくれないようです。
str(MATRIX2)
 int [1:4, 1:5] 1 6 11 16 2 7 12 17 3 8 ...

## すべての値が数字なのでかけ算ができます。3をかけてみます。
MATRIX2 * 3
     [,1] [,2] [,3] [,4] [,5]
[1,]    3    6    9   12   15
[2,]   18   21   24   27   30
[3,]   33   36   39   42   45
[4,]   48   51   54   57   60


## このようにmatrix行列は一つのベクトルを折り畳んで作られるため、
## 一つのベクトルと同じく含まれる値の種類は一種類(この場合は数値)のみです。
## むりやり文字列を入れたらどうなるでしょうか。
## [行番号,列番号]という要素指定の方法で文字列をいれて見ます。
MATRIX2
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
[3,]   11   12   13   14   15
[4,]   16   17   18   19   20

## [2行目,3列目]の要素を指定。8がある場所です。
MATRIX2[2,3]
[1] 8

## そこに文字列 "吉田"をむりやり入れる。
MATRIX2[2,3] <- "吉田"

## すべて""がついています。文字列の特徴です。
## class()はmatrixのままですが、STRucture()だとCHaRacter文字列
## となり、行列のすべての要素が文字列になってしまいました。
MATRIX2
     [,1] [,2] [,3]   [,4] [,5]
[1,] "1"  "2"  "3"    "4"  "5" 
[2,] "6"  "7"  "吉田" "9"  "10"
[3,] "11" "12" "13"   "14" "15"
[4,] "16" "17" "18"   "19" "20"
class(MATRIX2)
[1] "matrix"
str(MATRIX2)
 chr [1:4, 1:5] "1" "6" "11" "16" "2" "7" "12" "17" "3" "吉田" "13" "18" "4" "9" ...

## 当然、これでは計算はできません。
MATRIX2 * 3
Error: non-numeric argument to binary operator



#################### matrixとdata frameのちがい ####################

## ではmatrixとdata.frameの違いは何でしょう。
## 一言でいうと
## matrixは__一本__のベクトルを畳んだもの
## data.frameは__複数__のベクトルを束ねたもの
## です。
## 前者はあくまで一個のベクトルなので一種類のデータしか入りません。
## 後者は複数のベクトルなので、数値でも文字列でも好きに入れられます。


## 複数のベクトルを作ります。
numbers  <- seq(from=1, to=10, by=1)
letters  <- c("a","b","c","d","e","f","g","h","i","j")
LETTERS  <- toupper(c("a","b","c","d","e","f","g","h","i","j"))
hirakana <- c("あ","い","う","え","お","か","き","く","け","こ")
katakana <- c("ア","イ","ウ","エ","オ","カ","キ","ク","ケ","コ")

## データの中身はnumbersはNUMeric数値、他はCHaRacter文字列です。
str(numbers)
 num [1:10] 1 2 3 4 5 6 7 8 9 10
str(letters)
 chr [1:10] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

## 先ほどのベクトルたちを束ねます。
DATA.FRAME <- data.frame(
                         numbers,
                         letters,
                         LETTERS,
                         hirakana,
                         katakana
                         )

## 縦方向に束ねられたのがわかりますか。
DATA.FRAME
   numbers letters LETTERS hirakana katakana
1        1       a       A       あ       ア
2        2       b       B       い       イ
3        3       c       C       う       ウ
4        4       d       D       え       エ
5        5       e       E       お       オ
6        6       f       F       か       カ
7        7       g       G       き       キ
8        8       h       H       く       ク
9        9       i       I       け       ケ
10      10       j       J       こ       コ


## 3をかけてみるとエラーが出ますが1列目のnumbersはきちんと計算
## されています。1列目では数値が数値として保たれている訳です。
DATA.FRAME * 3
   numbers letters LETTERS hirakana katakana
1        3      NA      NA       NA       NA
2        6      NA      NA       NA       NA
3        9      NA      NA       NA       NA
4       12      NA      NA       NA       NA
5       15      NA      NA       NA       NA
6       18      NA      NA       NA       NA
7       21      NA      NA       NA       NA
8       24      NA      NA       NA       NA
9       27      NA      NA       NA       NA
10      30      NA      NA       NA       NA


## 構造をみると
## $ 変数名 : その変数の種類
## という表示で変数ごとに数値だったりfactor因子だったりします。
str(DATA.FRAME)
'data.frame':   10 obs. of  5 variables:
 $ numbers : num  1 2 3 4 5 6 7 8 9 10
 $ letters : Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10
 $ LETTERS : Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 6 7 8 9 10
 $ hirakana: Factor w/ 10 levels "あ","い","う",..: 1 2 3 4 5 6 7 8 9 10
 $ katakana: Factor w/ 10 levels "ア","イ","ウ",..: 1 2 3 4 5 6 7 8 9 10

## ここで初めて出てきた factor はカテゴリー変数のことです。
## 文字列CHaRactorと因子factorの違いは後者は統計処理に使えるという所にあります。
##
## 例えば患者名は文字列です。患者ごとにすべて違い集計することはありません。
## 性別はmale, femaleという変数はカテゴリー変数です、こちらは集計する
## という概念があります。
##
## Rでは .csvなどから取り込んだ文字列(male, femaleなど)は自動的になるべく
## カテゴリー変数として取り込んでくれます。




#################### list ####################

## Rのデータ構造の最上位概念のlist/リストについて説明します。

## 今までの説明でvectorとmatrixは一つのベクトルであり、一種類のデータのみ。
## data frameは複数のベクトルを束ねているので、束ねたベクトルの数だけ
## データ構造を持つことができることを話しました。

## このdata frameをさらに柔軟にしたのがlistです。

## 先ほどのように複数のベクトルを作ります。
## 先ほどとは違いそれぞれ長さが異なります。
numbers  <- seq(from=1, to=30, by=1)
letters  <- c("a","b","c","d","e","f","g","h","i")
LETTERS  <- toupper(c("a","b","c","d","e","f","g"))
hirakana <- c("あ","い","う","え","お","か","き","く","け","こ","さ")
katakana <- c("ア","イ","ウ","エ","オ","カ","キ","ク","ケ","コ","サ","シ")


## データフレームにしょうとすると長さが違うのでまとめられないと
## 泣き言をいわれてエラーになります。
DATA.FRAME2 <- data.frame(
                          numbers,
                          letters,
                          LETTERS,
                          hirakana,
                          katakana
                          )
Error: arguments imply differing number of rows: 30, 9, 7, 11, 12


## 心配はご無用。リストは細かいことは気にしません!
## 長さはもちろん、ベクトルでなくても大丈夫!
## このように雑多なものをまとめるときにリストが使われます。
LIST <- list(
             numbers,           # 長さ30の数値ベクトル
             letters,           # 長さ9の文字ベクトル
             LETTERS,           # 長さ7の文字ベクトル
             hirakana,          # 長さ11の文字ベクトル
             katakana,          # 長さ12の文字ベクトル
             MATRIX,            # 縦4 x 横5の行列!
             DATA.FRAME         # さっき作ったデータフレーム!
             )

## 長さが違うので表形式では表示できません。
## このため[[1]]つめの要素、、[[2]]つめの要素、、上から下にと表示されます。
LIST
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

[[2]]
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i"

[[3]]
[1] "A" "B" "C" "D" "E" "F" "G"

[[4]]
 [1] "あ" "い" "う" "え" "お" "か" "き" "く" "け" "こ" "さ"

[[5]]
 [1] "ア" "イ" "ウ" "エ" "オ" "カ" "キ" "ク" "ケ" "コ" "サ" "シ"

[[6]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

[[7]]
   numbers letters LETTERS hirakana katakana
1        1       a       A       あ       ア
2        2       b       B       い       イ
3        3       c       C       う       ウ
4        4       d       D       え       エ
5        5       e       E       お       オ
6        6       f       F       か       カ
7        7       g       G       き       キ
8        8       h       H       く       ク
9        9       i       I       け       ケ
10      10       j       J       こ       コ



## 1つめの要素、つまり長さ30の数値ベクトルを取り出すには
## [[1]]つめの要素と指定します。鍵括弧二つです。
LIST[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30


## 7つめの要素、つまりデータフレームを取り出すには[[7]]です。
LIST[[7]]
   numbers letters LETTERS hirakana katakana
1        1       a       A       あ       ア
2        2       b       B       い       イ
3        3       c       C       う       ウ
4        4       d       D       え       エ
5        5       e       E       お       オ
6        6       f       F       か       カ
7        7       g       G       き       キ
8        8       h       H       く       ク
9        9       i       I       け       ケ
10      10       j       J       こ       コ


## リストの7つの要素にすべて同じコマンドを作用させるには
## List APPLY()を使います。1つめにリスト名、FUN = にコマンド名を()なしで
## いれます。

## すべての要素のclass()をみてみます。6番目が行列、7番目がデータフレーム
## であることが分かります。
lapply(LIST, FUN = class)
[[1]]
[1] "numeric"

[[2]]
[1] "character"

[[3]]
[1] "character"

[[4]]
[1] "character"

[[5]]
[1] "character"

[[6]]
[1] "matrix"

[[7]]
[1] "data.frame"



## summary()を行ってみます。あまり意味がありませんがそれぞれに行われます。
lapply(LIST, FUN = summary)
[[1]]
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1.00    8.25   15.50   15.50   22.80   30.00 

[[2]]
   Length     Class      Mode 
        9 character character 

[[3]]
   Length     Class      Mode 
        7 character character 

[[4]]
   Length     Class      Mode 
       11 character character 

[[5]]
   Length     Class      Mode 
       12 character character 

[[6]]
       V1             V2             V3              V4             V5      
 Min.   :1.00   Min.   :5.00   Min.   : 9.00   Min.   :13.0   Min.   :17.0  
 1st Qu.:1.75   1st Qu.:5.75   1st Qu.: 9.75   1st Qu.:13.8   1st Qu.:17.8  
 Median :2.50   Median :6.50   Median :10.50   Median :14.5   Median :18.5  
 Mean   :2.50   Mean   :6.50   Mean   :10.50   Mean   :14.5   Mean   :18.5  
 3rd Qu.:3.25   3rd Qu.:7.25   3rd Qu.:11.25   3rd Qu.:15.2   3rd Qu.:19.2  
 Max.   :4.00   Max.   :8.00   Max.   :12.00   Max.   :16.0   Max.   :20.0  

[[7]]
    numbers         letters     LETTERS     hirakana    katakana
 Min.   : 1.00   a      :1   A      :1   あ     :1   ア     :1  
 1st Qu.: 3.25   b      :1   B      :1   い     :1   イ     :1  
 Median : 5.50   c      :1   C      :1   う     :1   ウ     :1  
 Mean   : 5.50   d      :1   D      :1   え     :1   エ     :1  
 3rd Qu.: 7.75   e      :1   E      :1   お     :1   オ     :1  
 Max.   :10.00   f      :1   F      :1   か     :1   カ     :1  
                 (Other):4   (Other):4   (Other):4   (Other):4