Mukku John Blog

取り組んでいること を つらつら と

Rプログラミング入門 8回目

Rのオブジェクト

Rのデータ型、データ構造を学んでいきます。

アトミックベクトル

単純なデータのベクトルです。

> die <- c(1,2,3,4,5,6)
> die
[1] 1 2 3 4 5 6

アトミックベクトルかどうかを確認するためには、is.vector関数を用います。

> is.vector(die)
[1] TRUE

要素が1個でも作成でき、1個の値を長さ1のアトミックベクトルとして扱います。

> five <- 5
> five
[1] 5
> is.vector(five)
[1] TRUE

アトミックベクトルには、1つの同じデータ型しか格納できません。
Rには、double,integer,character,logical,complex,rawの6つのデータ型を認識します。

double 倍精度浮動小数点数

通常の数値は、double型になります。
型を確認するためには、typeof関数を用います。

> die <- c(1,2,3,4,5,6)
> die
[1] 1 2 3 4 5 6
> typeof(die)
[1] "double"

integer 整数

少数部がない数値を表します。数値に"L"サフィックスを付与します。

> int <- c(-1L,1L,2L)
> int
[1] -1  1  2
> typeof(int)
[1] "integer"
浮動小数点誤差

他の言語でも同じですが、数値の扱いは厳密に行う必要があります。
倍精度浮動小数点数の正しい有効桁数には、限りがあります。

> sqrt(2)^2-2
[1] 4.440892e-16

integer型のオブジェクトで計算させても、0にならないため、
Rが計算する際には、倍精度浮動小数点数を用いているのでしょうか。

> num2 <- 2L
> sqrt(num2)^num2-num2
[1] 4.440892e-16

character 文字

クォートで囲むと文字になります。

> text <- c("ace", "hearts")
> is.vector(text)
[1] TRUE
> typeof(text)
[1] "character"

logical 論理値

TRUEとFALSEです。TとFを省略形として扱うことができます。

> logic <- c(TRUE,FALSE,FALSE)
> logic
[1]  TRUE FALSE FALSE
> typeof(logic)
[1] "logical"
> typeof(F)
[1] "logical"

complex 複素数 と raw バイナリ

複素数を作成するには、数値に"i"サフィックスを付与します。
(複素数なんて高校以来触れたこともありません。実数と虚数のワードくらいしか。。。i×i = -1のiが虚数でしたっけ?)

> comp <- c(1+1i,1+2i,1+3i)
> comp
[1] 1+1i 1+2i 1+3i
> typeof(comp)
[1] "complex"

バイナリを作成するには、今までのアトミックベクトルの作成方法とは異なり、
raw関数を用います。

> raw(3)
[1] 00 00 00
> typeof(raw(3))
[1] "raw"

属性

属性とは、アトミックベクトルに付与できるメタデータです。
属性を確認するためには、attributes関数を用います。

> comp
[1] 1+1i 1+2i 1+3i
> names(comp) <- c("col_1","col_2","col_3")
> comp
col_1 col_2 col_3 
1+1i 1+2i 1+3i
> attributes(comp)
$names
[1] "col_1" "col_2" "col_3"

アトミックベクトルに与えられる一般的な属性は、名前、次元、クラスになります。

名前属性

アトミックベクトルの各要素に、ヘッダのような名称を付ける事ができます。
付け方は、namesヘルパー関数に、文字ベクトルを割り当てます。

> names(die)
NULL
> names(die) <- c("one","two","three","four","five","six")
> names(die)
[1] "one"   "two"   "three" "four"  "five"  "six"  
> attributes(die)
$names
[1] "one"   "two"   "three" "four"  "five"  "six"  

> die
  one   two three  four  five   six 
    1     2     3     4     5     6 

名前属性は、ベクトルの値に影響を与えません。

> die + 1
  one   two three  four  five   six 
    2     3     4     5     6     7 
> die - 1
  one   two three  four  five   six 
    0     1     2     3     4     5 
> die
  one   two three  four  five   six 
    1     2     3     4     5     6 

名前を変更するには、namesに新しい文字ベクトルを割り当てます。

> names(die) <- c("uno","dos","tres","cuatro","chinco","seis")
> die
   uno    dos   tres cuatro chinco   seis 
     1      2      3      4      5      6

名前属性を取り除くには、namesにNULLを割り当てます。

> names(die) <- NULL
> die
[1] 1 2 3 4 5 6

次元属性

1次元配列であるアトミックベクトルを、n次元配列に変換できます。
変換するためには、dim属性に長さnの数値ベクトルを割り当てます。
2×3行列に構成します

> dim(die) <- c(2,3)
> die
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

再構成するためには、dim属性に再度割り当てなおします。

> dim(die) <- c(3,2)
> die
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

1×2×3の3次元配列も構成できます。

> dim(die) <- c(1,2,3)
> die
, , 1

     [,1] [,2]
[1,]    1    2

, , 2

     [,1] [,2]
[1,]    3    4

, , 3

     [,1] [,2]
[1,]    5    6

Rでは必ず”行”が先になり、”列”ごとに値が構成されます。
この構成を制御するためには、matrix関数、array関数を用います。

行列

matrix関数を利用して、次元属性の行列を制御できます。
2行の行列オブジェクトを作成します。

> m <- matrix(die, nrow = 2)
> m
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

typeof関数とattributes関数を用いて、
データ型と属性を確認してみます。

> typeof(m)
[1] "double"
> attributes(m)
$dim
[1] 2 3

データ型は、dieオブジェクトと同じdouble型で
属性に、dimである次元属性が設定されています。

2列の行列オブジェクトを作成します。

> m <- matrix(die, ncol = 2)
> m
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

matrix関数は、byrow引数の使い方を変更すると、列ごとに並んでいた要素を行ごとに変更できます。

> m <- matrix(die,nrow = 2, byrow = TRUE)
> m
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
配列

array関数を利用して、n次元配列オブジェクトを作成します。
matrix関数のように、行列の配置など指定できません。
11~14、21~24、31~34を2行2列3スライスの3次元配列にします。

> ar <- array(c(11:14,21:24,31:34), c(2,2,3))
> ar
, , 1

     [,1] [,2]
[1,]   11   13
[2,]   12   14

, , 2

     [,1] [,2]
[1,]   21   23
[2,]   22   24

, , 3

     [,1] [,2]
[1,]   31   33
[2,]   32   34

matrix関数を用いた次元属性の指定と同じように
データ型と属性を確認します。

> typeof(ar)
[1] "integer"
> attributes(ar)
$dim
[1] 2 2 3

integer型(なぜ?)と、次元属性が設定されているのが分かります。

double型とinteger型の指定

array関数の最後で気になったので見てみました。

> dtype <- c(11,12,13,14)
> typeof(dtype)
[1] "double"
> itype <- 11:14
> typeof(itype)
[1] "integer"

上記の様に、指定の仕方で異なります。
もちろん、要素の値は同じです。

> dtype
[1] 11 12 13 14
> itype
[1] 11 12 13 14

クラス属性

属性に戻ります。
クラス属性はアトミックベクトルの特殊形を表します。
Rは、このクラス属性に基づいて、オブジェクトの処理方法を決定します。


比較して、確認がしやすいように、同じ要素を持つオブジェクトを用意し、
片方のオブジェクトだけ次元属性を設定しておきます。

> die
[1] 1 2 3 4 5 6
> die2
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

データ型はそれぞれ変わりません。

> typeof(die)
[1] "double"
> typeof(die2)
[1] "double"

ただしクラス属性が変わります。
dieオブジェクトは数値、die2オブジェクトはmatrixとなっています。

> class(die)
[1] "numeric"
> class(die2)
[1] "matrix"

つまり、die2オブジェクトは、倍精度浮動小数点数のデータ型で、matrixクラスのオブジェクトです。
(dieオブジェクトは、倍精度浮動小数点数のデータ型で、numericクラスのオブジェクト)

Rの関数は、クラス属性に基づいてオブジェクトの操作が行われます。
dieオブジェクトとdie2オブジェクトは、データ型が倍精度浮動小数点数と同じですが、
numericクラスと、matrixクラスでは、演算の仕方を分けて行ってくれます。

> die + 1
[1] 2 3 4 5 6 7
> die2 + 1
     [,1] [,2] [,3]
[1,]    2    4    6
[2,]    3    5    7
日付と時刻

クラス属性について、理解を深めるために、日付と時刻のクラスを見ていきます。
Sys.time関数を用います。

> now <- Sys.time()
> now
[1] "2016-07-03 20:41:16 JST"
> typeof(now)
[1] "double"
> class(now)
[1] "POSIXct" "POSIXt" 

nowオブジェクトは、doubleデータ型ですが、クラス属性は、"POSIXct"と"POSIXt"を持っています。
POSIXctは日付と時刻を扱うフレームワークで、1970年1月1日午前0時(UTC)からの秒数で表現されます。

そこで、nowオブジェクトのクラス属性を取り除いてみます。

> unclass(now)
[1] 1467546077

今は、1970年1月1日午前0時(UTC)から1,467,546,077秒後です。と言われても。。。
なのでdoubleデータ型のオブジェクトに、
"POSIXct"と"POSIXt"のクラス属性を設定してみます。

> now2 <- 1467546077
> now2
[1] 1467546077
> class(now2) <-c("POSIXct","POSIXT")
> now2
[1] "2016-07-03 20:41:17 JST"

doubleデータ型のオブジェクトnow2が、"POSIXct"と"POSIXt"のクラス属性を設定することで
日付と時刻を表現するように変わりました。

ファクタ

Rによく登場するデータクラスで、アトミックデータ型と学んでおくべきクラスです。
分類情報を格納するための手段で、factor関数にアトミックベクトルを渡す事で作成ができます。

> gender <- factor(c("male","female","female","male"))
> gender
[1] male   female female male  
Levels: female male
> typeof(gender)
[1] "integer"
> attributes(gender)
$levels
[1] "female" "male"  

$class
[1] "factor"

genderオブジェクトに、"male"、"female"から構成される文字ベクトルのfactor関数出力を割り当てています。
attributes関数で、属性を確認すると、
levels属性に、分類分けされた要素と、class属性にfactorクラスが設定されています。

unclass関数を用いると、どのように値を保持しているか確認できます。

> unclass(gender)
[1] 2 1 1 2
attr(,"levels")
[1] "female" "male"

as.character関数を用いて、文字列に変換することができます。

> as.character(gender)
[1] "male"   "female" "female" "male"

factorクラスを用いると、ラベル付けされた要素を分類しやすそうな感触が持てます。
(文字列より、数値で行った方が良さそうですからね。)

今日はここまで。