【R】データ型とデータ構造をこねくり回す


データ型や構造は調べればすぐにhitするものの、
毎回「あれこれどうやるんだっけ」となりやすいので、比較的よく使うものこねくり回して覚えます。


#型と構造
R上で扱えるものには型と構造がある。
型：数字や文字列など
構造：ベクトルやリストやデータフレームなど

##型について
numeric(num)：実数（有理数 + 無理数）
complex(cplx)：複素数（実数 + 虚数）
character(chr)：文字列
logical(logi)：論理値
integer(int)：整数（正負の自然数と0）
など

<details><summary>実行環境</summary>
・R version 4.0.2 (2020-06-22)
 Platform: x86_64-apple-darwin17.0 (64-bit)
 Running under: macOS Catalina 10.15.7
・RStudio Version 1.3.959
</details>

```r
#> は実際の入力を指します
#実数
> data <- 3.5
> mode(data)
[1] "numeric"
> is.numeric(data)
[1] TRUE

#整数とはみなされない
> data <- 3
> mode(data)
[1] "numeric"
> is.integer(data)
[1] FALSE
> is.numeric(data)
[1] TRUE

#整数であることを示すには「L」を付ける 
> data <- -3L
> mode(data)
[1] "numeric"
> is.integer(data)
[1] TRUE
> is.numeric(data)
[1] TRUE
> data
[1] -3


#複素数
> data <- 3+2i
> mode(data)
[1] "complex"

#純虚数だけ入れると実部は0になる
> data <- 2i
> mode(data)
[1] "complex"
> data
[1] 0+2i

#文字
> data <- "test"
> mode(data)
[1] "character"
 
#論理値
> data <- TRUE
> mode(data)
[1] "logical"

>data <- FALSE
> mode(data)
[1] "logical"

#エラーになる
> data <- True
エラー:  オブジェクト 'True' がありません  
```


##構造について
種類としてはvector,matrix,array,list,dataframeなど。
dataframeをよく使うけれど、いざ他を使おうとすると忘れる。

###vector
data <- c(1,2,3,4,5)のような書き方。
中身は数字でも文字でもなんでも入る。
ただし、例えばc(1,"2")みたいな書き方をすると強制的に全部charactorになる。
つまり、一種類の型しか扱えない。
>character > complex > numeric > logical > NULL
>ベクトルの要素は全て同じ型なので，異なった型のデータを集めてベクトルを作ろうとすると上記の変換規則によって『最も大きい』型に揃えられる

http://cse.naro.affrc.go.jp/takezawa/r-tips/r/25.html

```r:
> v_data1<-c("test","test")
> v_data2<-c(1,2)
> v_data3<-c(1,"2")

> v_data1
[1]"test""test"
> v_data2
[1]12
> v_data3
[1]"1""2"
> is.vector(v_data1)
[1]TRUE
> is.vector(v_data2)
[1]TRUE
> is.vector(v_data3)
[1]TRUE
> mode(v_data1[0])
[1]"character"
> mode(v_data2[0])
[1]"numeric"
#文字として扱われる
> mode(v_data3[0])
[1]"character"
```

###matrix
ベクトルが線、行列は面をイメージする。
data[行,列]のように指定できる。

```r:
> m_data1 <- matrix(1:6, nrow=2, ncol=3)
#2行3列として表示される

#要素は標準では左上から下に順番に埋められる
> m_data1
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

> is.matrix(m_data1)
[1] TRUE

#要素を取り出す
> m_data1[2,3]
[1] 5
> m_data1[2:5]
[1] 2 3 4 5
> m_data1[2,]
[1] 2 4 6
> m_data1[,3]
[1] 5 6

#範囲を超えて指定するとエラー
> m_data1[,4]
 m_data1[, 4] でエラー:  添え字が許される範囲外です 

#rbind()やcbind()でベクトルを結合することが可能
> rbind(c(1,2,3), c(4,5,6), c(7,8,9)) 
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

> cbind(c(1,2,3), c(4,5,6), c(7,8,9)) 
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

#引数にbyrow=Tをつけてあげると表示順を左から右へ変更することも可能。
> matrix(1:6, nrow=2, ncol=3, byrow=T)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
```

###array
行列は、配列は3次元以上を表現することが可能。

dimの引数にベクトルをわたす。 例えばc(2,3,3)
→ 2×3の行列が3つ表示される

```r:
> a_data1 <-array(1:18, dim=c(2,3,3))
> a_data1
, , 1

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

, , 2

     [,1] [,2] [,3]
[1,]    7    9   11
[2,]    8   10   12

, , 3

     [,1] [,2] [,3]
[1,]   13   15   17
[2,]   14   16   18

#各行列の1行目が表示
> a_data1[1,,]
     [,1] [,2] [,3]
[1,]    1    7   13
[2,]    3    9   15
[3,]    5   11   17

#aperm()で囲むと転置される
> aperm(a_data1[1,,])
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    7    9   11
[3,]   13   15   17

#各行列の2列目が取り出せる
> a_data1[,2,]
     [,1] [,2] [,3]
[1,]    3    9   15
[2,]    4   10   16

#行列の2つめを取り出せる
> a_data1[,,2]
     [,1] [,2] [,3]
[1,]    7    9   11
[2,]    8   10   12

> is.matrix(a_data1[,,2])
[1] TRUE

#matrixから取り出すような感じで書ける
> a_data1[,,2][2,2]
[1] 10

> is.vector(a_data1[,,2][2,2])
[1] TRUE

#4×3×2として表せる
> aperm(array(1:24, dim=c(2,3,4))) 
, , 1

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    7    9   11
[3,]   13   15   17
[4,]   19   21   23

, , 2

     [,1] [,2] [,3]
[1,]    2    4    6
[2,]    8   10   12
[3,]   14   16   18
[4,]   20   22   24

```


###list
これまでのvectorやmatrixと違い、複数の型のデータをまとめておくことができる。

```r:

#listの中にさらにlistを作ることもできる
> l_data1 <- list(1:5, list("aaaaa", c(T, F)))
> l_data1
[[1]]
[1] 1 2 3 4 5

[[2]]
[[2]][[1]]
[1] "abcde"

[[2]][[2]]
[1]  TRUE FALSE

#vectorとしてもtrueが返る
> is.vector(l_data1)
[1] TRUE
> is.list(l_data1)
[1] TRUE

#数字を一部だけ取り出したい
> l_data1[1]
[[1]]
[1] 1 2 3 4 5

#がこれでは取り出せない
> l_data1[1][2]
[[1]]
NULL

#一つ目の要素を取り出すには[]で囲む
> l_data1[[1]]
[1] 1 2 3 4 5

> is.vector(l_data1[[1]])
[1] TRUE
> is.list(l_data1[[1]])
[1] FALSE

#vectorとして扱える
> l_data1[[1]][2:4]
[1] 2 3 4

#リストの2つ目の中から1つ目を取得する
> l_data1[[2]][1]
[[1]]
[1] "abcde"

#文字列を切り出す
> substring(l_data1[[2]][1],1,2)
[1] "ab"
```


###dataframe
何かと扱いやすい。
list同様に様々な型のデータを持たせることが可能。

```r:
> id <- c("a","b","c","d","e")
> height <- c(166,164,182,171,165)
> weight <- c(52,52,75,82,60)
> data <- data.frame(ID=id, HEIGHT=height, WEIGHT=weight)
> data
  ID HEIGHT WEIGHT
1  a    166     52
2  b    164     52
3  c    182     75
4  d    171     82
5  e    165     60

> data$HEIGHT
[1] 166 164 182 171 165

> data[,2]
[1] 166 164 182 171 165
> is.vector(data[,2])
[1] TRUE

> data[2]
  HEIGHT
1    166
2    164
3    182
4    171
5    165
> is.list(data[2])
[1] TRUE

> data[1,1]
[1] "a"

> data[,2:3]
 HEIGHT WEIGHT
1    166     52
2    164     52
3    182     75
4    171     82
5    165     60

> data[3:4,]
 ID HEIGHT WEIGHT
3  c    182     75
4  d    171     82

#数が揃ってないとエラーになる
> id <- c("a","b","c","d","e","f")
> height <- c(166,164,182,171,165)
> weight <- c(52,52,75,82,60)
> data <- data.frame(ID=id, HEIGHT=height, WEIGHT=weight)
data.frame(ID = id, HEIGHT = height, WEIGHT = weight) でエラー: 
   引数に異なる列数のデータフレームが含まれています: 6, 5 

#値を上書き
> data[1,1] <- "A"
> data
  ID HEIGHT WEIGHT
1  A    166     52
2  b    164     52
3  c    182     75
4  d    171     82
5  e    165     60

#列を上書き
> data[[2]]  <- c(150,150,150,150,150)
> data
  ID HEIGHT WEIGHT
1  A    150     52
2  b    150     52
3  c    150     75
4  d    150     82
5  e    150     60

#横方向に上書き
> data[3,] <- c("C",140,50)
> data
  ID HEIGHT WEIGHT
1  A    150     52
2  b    150     52
3  C    140     50
4  d    150     82
5  e    150     60

#一度文字を入れてしまうと、先のルールからcharacterになってしまう
> data[4,] <- c("C","140",50)
> mode(data[[2]])
[1] "character"

> data[4,] <- c("C",140,50)
> mode(data[[2]]) 
[1] "character"#戻らない

#変換する
> data[[2]] <- as.numeric(data[[2]])
> mode(data[[2]])
[1] "numeric"

```
dataframeの要素の取り方をまとめるとこんな感じでしょうか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128052/21ad5885-b7df-ff5b-a38e-b83763a30a86.png)

#参考

http://cse.naro.affrc.go.jp/takezawa/r-tips/r.html