目次

概要

R言語は、統計解析向けのプログラミング言語及びその開発実行環境。

インストール

以下の URLからインストーラをダウンロードしてインストール

基本操作

開始と終了

Rがインストールされている環境で r を入力すれば、R がインタラクティブモードで起動する。

r

R version 3.5.2 (2018-12-20) -- "Eggshell Igloo"
Copyright (C) 2018 The R Foundation for Statistical Computing
.
.
.
'demo()' と入力すればデモをみることができます。 
'help()' とすればオンラインヘルプが出ます。 
'help.start()' で HTML ブラウザによるヘルプがみられます。 
'q()' と入力すれば R を終了します。 

> 

終了は q()

> q()
Save workspace image? [y/n/c]: n

※ --save または --no-save オプション付きで起動した場合は、終了時の確認メッセージは表示されない。

ヘルプの表示方法

?コマンド名 または help(コマンド名) でコマンドのヘルプを表示する事ができる。

例)

> ?read.table
read.table                package:utils                R Documentation
    .
    .
Usage:

     read.table(file, header = FALSE, sep = "", quote = "\"'",
                dec = ".", numerals = c("allow.loss", "warn.loss", "no.loss"),
                row.names, col.names, as.is = !stringsAsFactors,
                na.strings = "NA", colClasses = NA, nrows = -1,
                skip = 0, check.names = TRUE, fill = !blank.lines.skip,
                strip.white = FALSE, blank.lines.skip = TRUE,
        .
        .

変数への代入

変数への代入は <- または -> で行う。
以下は、1〜5までの連続した値のベクトルを生成し、x という変数に代入している。

> x <- c(1:5)
> x
[1] 1 2 3 4 5

()で囲むと変数に代入すると同時に内容を表示する事ができる。

> (x <- c(1:5))
[1] 1 2 3 4 5

複数の変数に代入する事も可能

> x <- y <- 1:5
> x
[1] 1 2 3 4 5
> y
[1] 1 2 3 4 5

左辺と右辺は入れ替える事も可能

> 1:5 -> x -> y
> x
[1] 1 2 3 4 5
> y
[1] 1 2 3 4 5

グローバル変数への代入

グローバル変数への代入は <<- で行なう。

> count <- 0
> mycount <- function(num){
+     count <<- count + num
+ }
> mycount(1)
> mycount(2)
> mycount(3)
> count
[1] 6

連続した値の生成

n:m と記述する事で連続した値を生成する事ができる。

> 1:5
[1] 1 2 3 4 5

開始値, 終了値, 増分 を指定して値を生成する場合は seq を使用する。

> seq(1, 5, 2)
[1] 1 3 5

繰り返し値の生成

任意の値をN個分繰り返すには rep を使用する。

> rep(1, 5)
[1] 1 1 1 1 1

値には ベクトルを指定する事もできる。

> rep(1:3, 5)
 [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3

定義済みの変数一覧を表示する

定義した全ての変数の一覧を ls() で確認する事ができる。

> x <- 1:10
> y <- 101:110
> ls()
[1] "x" "y"

使わない変数を消す

rm で定義した変数を削除する事ができる。

> x <- 1:10
> y <- 101:110
> ls()
[1] "x" "y"
> rm(y)
> ls()
[1] "x"

rm の 名前付き引数 list に変数名の一覧を指定して削除する事もできる。
※以下は、全ての変数を削除する例。

> x <- 1:10
> y <- 101:110
> ls()
[1] "x" "y"
> rm(list=ls())
> ls()
character(0)

外部スクリプトの読み込み

別ファイルに保存したスクリプトを読み込むには source を使用する。

test.R

x = c(1:5)

実行例

> source("test.R")
> x
[1] 1 2 3 4 5

ワークスペースの保存

Rでは作業中のワークスペースの状態をワークスペースに保存しておき、後から復元する事ができる。

変数 x, y, z を定義してRを終了(確認で y を入力)

R
> x <- 1:10
> y <- 101:110
> z <- 201:210
> q()
Save workspace image? [y/n/c]: y

再開

R
 .
 .
 [以前にセーブされたワークスペースを復帰します] 
> ls()
[1] "x" "y" "z"

R を --save または --no-save オプション付きで起動した場合は、Rの終了時に確認メッセージは表示されない。
※自動的に保存して(または保存しないで)終了する。

尚、変数 及び 履歴情報は作業ディレクトリ配下の .RData 及び .Rhistory というファイルに保存されている。
※これらのファイルを消せばワークスペースの状態を初期化できる。

コマンドラインから R のスクリプトを実行する

test.R

x <- 1:10
cat(x)

実行

rscript test.R
1 2 3 4 5 6 7 8 9 10

コマンドライン引数を受け取る

commandArgs(trailingOnly=T) でコマンドライン引数を受け取る事ができる。
trailingOnly = T を付けないと、取得内容に rscript 自体への引数も含まれてしまう為、注意。

get_args.R

args <- commandArgs(trailingOnly=T)

for (i in seq(length(args))) {
    arg <- args[i]
    cat("arg", i, " = ", arg, "\n", sep="")
}

実行結果

rscript get_args.R ABC 123
arg1 = ABC
arg2 = 123

定数など

以下のビルトイン定数やオブジェクトが使用できる。

定数名説明
NULLNULLオブジェクト。※null値の判定は is.null(変数) で可能。
NaN未定義を示す値
TRUE, T真偽値のTrue
FALSE, F真偽値のFalse
LETTERSA〜Zのベクトル
lettersa〜zのベクトル
month.abb1月〜12月の略称のベクトル
month.name1月〜12月のベクトル
piπ


> NULL
NULL
> NaN
[1] NaN
> T
[1] TRUE
> F
[1] FALSE
> LETTERS
 [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
> letters
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
> month.abb
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
> month.name
 [1] "January"   "February"  "March"     "April"     "May"       "June"      "July"      "August"    "September"
[10] "October"   "November"  "December" 
> pi
[1] 3.141593

オブジェクト内容の表示

変数名のタイプによる表示

> x <- 1:10
> x
 [1]  1  2  3  4  5  6  7  8  9 10

print による表示

> x <- 1:10
> print(x)
 [1]  1  2  3  4  5  6  7  8  9 10

sprintf

書式付きでオブジェクトを表示する場合には sprint を使用する。

> sprintf("%3.2f", 123.456)
[1] "123.46"

cat

cat を使用すれば文字列をダブルクォーテーションなしで表示できる。

> str1 = "ABCDEFG"
> cat(str1)
ABCDEFG

str

str を使用すると、オブジェクトの内容をデータ型などの情報付きで表示できる。

> str1 = "123"
> str(str1)
 chr "123"

基本的な関数

サイズを調べる

length、ncol、nrow でベクトルや行列等の長さを調べる事ができる。
また、文字列の長さを調べる場合は length でなく nchar を使用する。

> x <- matrix(1:20, ncol = 5)
> x
     [,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
> length(x)  # 全体のサイズ
[1] 20
> ncol(x)     # 列数
[1] 5
> nrow(x)    # 行数
[1] 4
> nchar("12345678")    # 文字列の長さ
[1] 8

合計/最小/最大/平均/中央値/分散/標準偏差

> x <- c(1, 2, 3, 4, 5)
> # 合計
> sum(x)
[1] 15
> # 最小
> min(x)
[1] 1
> # 最大
> max(x)
[1] 5
> # 平均
> mean(x)
[1] 3
> # 中央値
> median(x)
[1] 3
> # 分散
> var(x)
[1] 2.5
> # 標準偏差
> sd(x)
[1] 1.581139

行/列ごとの統計値

x <- matrix(1:9, nrow=3, byrow=T)
# 行ごとの合計
rowSums(x)
# 列毎の合計
colSums(x)
# 行ごとの平均
rowMeans(x)
# 列ごとの平均
colMeans(x)
# 行ごとの中央値
> apply(x, 1, median)
[1] 2 5 8
# 行ごとの標準偏差
> apply(x, 1, sd)
[1] 1 1 1

※専用の関数がない場合は、apply を使用して求める事ができる。

summary による列情報の概要表示

summary で列毎の概要を表示する事ができる。

> x <- matrix(1:20, ncol = 5)
> colnames(x) <- paste("col", 1:ncol(x), sep = "")
> rownames(x) <- paste("No", 1:nrow(x), sep = "")
> x
     col1 col2 col3 col4 col5
No1    1    5    9   13   17
No2    2    6   10   14   18
No3    3    7   11   15   19
No4    4    8   12   16   20
> summary(x)
      col1           col2           col3            col4            col5      
 Min.   :1.00   Min.   :5.00   Min.   : 9.00   Min.   :13.00   Min.   :17.00  
 1st Qu.:1.75   1st Qu.:5.75   1st Qu.: 9.75   1st Qu.:13.75   1st Qu.:17.75  
 Median :2.50   Median :6.50   Median :10.50   Median :14.50   Median :18.50  
 Mean   :2.50   Mean   :6.50   Mean   :10.50   Mean   :14.50   Mean   :18.50  
 3rd Qu.:3.25   3rd Qu.:7.25   3rd Qu.:11.25   3rd Qu.:15.25   3rd Qu.:19.25  
 Max.   :4.00   Max.   :8.00   Max.   :12.00   Max.   :16.00   Max.   :20.00

実行時間の計測

proc.time を使用する場合

> t1 <- proc.time()
> for (i in 1:1000000) {
+     NULL
+ }
> proc.time() - t1
   ユーザ   システム       経過  
     0.015      0.001      0.015

system.time を使用する場合

> system.time({
+     for (i in 1:1000000) {
+         NULL
+     }
+ })
   ユーザ   システム       経過  
     0.012      0.000      0.012

処理制御

条件分岐

> x <- 10
> if (x == 5) {
+     cat("x == 5")
+ } else if (x < 8) {
+     cat("x < 8")
+ } else {
+     cat("other")
+ }
other

forループ

繰り返し処理には for文が使用できる。
ただし R の for文は遅いので処理を関数化して apply系で記述する方が高速に動作する。

> for (i in 1:5) {
+   print(i)
+ }
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

whileループ

while ループを使用する事もできる。
※例では示さないが break も使用可能。

> i <- 1
> while(i <= 10) {
+     cat(sprintf("i = %d\n", i))
+     i <- i + 1
+ }
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10

switch文

TODO:

関数の定義

関数名 <- function(引数,...) で関数を定義する事ができる。

> myfunc <- function(x) {
+   return (x*2)
+ }
> 
> myfunc(2)
[1] 4
> myfunc(10)
[1] 100

パイプの使用

シェル等で使用する | と同等の機能は「%>%」 で実現できる。
dplyr::group_by や summarise をパイプと共に利用するとかなり便利。

> # dplyr のインストール(グループ化で使用する)
> install.packages("dplyr")
>
> # dplyrの読み込み
> library(dplyr)
> sex <- c("W", "M", "M", "M", "W", "W", "W", "W", "M", "W")
> state <- c("Osaka", "Tokyo", "Osaka", "Osaka", "Nagoya", "Osaka", "Tokyo", "Tokyo", "Nagoya", "Tokyo")
> height <- c(170.5, 175.4, 171.2, 173.6, 169.8, 165.2, 178.1, 165.5, 173.2, 172.9)
> パイプを使用して都道府県毎にグループ化
> data.frame(Sex=sex, State=state, Height=height) %>% dplyr::group_by(State) %>% dplyr::summarise(Count = n())
# A tibble: 3 x 2
  State  Count
    
1 Nagoya     2
2 Osaka      4
3 Tokyo      4

例外処理

> tryCatch({
+   print("start!")
+   rbind(x, c(1:10))
+   print("end!")
+ }
+ , warning = function(e) {
+   print("warning")
+   print(e)
+ }
+ , error = function(e) {
+   print("error!")
+   print(e)
+ }
+ , finally = {
+   print("finally!")
+ })
[1] "start!"
[1] "error!"
<simpleError in rbind(x, c(1:10)):  オブジェクト 'x' がありません >
[1] "finally!"

メッセージを表示する

いろいろやり方はあるが、プログラムの進捗状況などを表示する際には message や warning が使用できる。

> cat("cat!", "\n")
cat! 
> print("print!")
[1] "print!"
> message("message!")
message!
> warning("warning!")
 警告メッセージ: 
warning! 

メッセージの表示を抑制する

suppressMessages で message の表示を抑制する事ができる。

> suppressMessages({
+   message("test message")
+   warning("test warning")
+ })
 警告メッセージ: 
 withCallingHandlers(expr, message = function(c) invokeRestart("muffleMessage")) で: 
  test warning
})

suppressWarnings で warning の表示を抑制する事ができる。

> suppressWarnings({
+   message("test message")
+   warning("test warning")
+ })
test message

cat や print の表示を抑制する場合は、sink や capture.output で出力をファイルに吐く。

sink("dummy.txt")
print("test print!")
cat("test cat!", "\n")
sink()

capture.output(
  cat("test cat!", "\n"),
  print("test print!"),
  file = "caputure.txt",
  type = c("output", "message")
)

文字列の操作

文字列の結合

> paste("abc", "def", sep="")
[1] "abcdef"

文字列の分割

strsplit で文字列を分割する事ができる。
※ただし結果はリストオブジェクトなので、unlist 等でベクトルに変換する等の処置が必要。

> text <- "abc,def,ghi"
> res <- strsplit(text, ",")
> res
[[1]]
[1] "abc" "def" "ghi"

> res[[1]]
[1] "abc" "def" "ghi"
> res[[1]][1]
[1] "abc"
> unlist(res)[1]
[1] "abc"

文字列の切り出し

substr で文字列を部分的に切り出す事が可能。

> substr("1234567890", 2, 3)
[1] "23"
> substr(c("1234567890", "abcdefghijklmn"), 2, 3)
[1] "23" "bc"

文字列の置換

sub または gsub で文字列の置換を行う事ができる。
引数には文字列 以外にベクトルや行列も指定可能。(各要素に対して置換が行われる)

> sub("l", "L", c("Hello R!", "Hello Python!"))     # マッチする最初の1文字を置換
[1] "HeLlo R!"      "HeLlo Python!"
> gsub("l", "L", c("Hello R!", "Hello Python!"))    # マッチする全ての文字を置換
[1] "HeLLo R!"      "HeLLo Python!"
> gsub("[^a-zA-Z ]", "#", c("Hello R!", "Hello Python!"))    # 正規表現で置換
[1] "Hello R#"      "Hello Python#"

文字列の長さを調べる

nchar

> length("abc")   # lengthでは正しい長さは得られない
[1] 1
> nchar("abc")    # nchar だと正しい長さが得られる
[1] 3

文字列の大文字/小文字を変換する

大文字に変換

> toupper("abc")
[1] "ABC"
> toupper(c("abc", "def"))
[1] "ABC" "DEF"

小文字に変換

> tolower("ABC")
[1] "abc"
> tolower(c("ABC", "DEF"))
[1] "abc" "def"

ベクトルの操作

ベクトルの生成

c() でベクトルの生成を行う事ができる。

> x <- c(100,200,300)
> x
[1] 100 200 300

連続した値のベクトルであれば n:m でも生成可能。

> x <- 1:5
> x
[1] 1 2 3 4 5

他にファイルからデータを読み込んでデータフレームを生成する事も可能。( CSVファイルの入出力 を参照 )

ベクトルの要素へのアクセス

要素番号を指定して特定の要素にアクセスする事ができる。

> x <- 10:20
> x
 [1] 10 11 12 13 14 15 16 17 18 19 20
> x[2] <- 99
> x
 [1] 10 99 12 13 14 15 16 17 18 19 20

ベクトルの特定の値を書き換える

要素番号を指定して特定の要素にアクセスする事ができる。

> x <- 10:20
> x
 [1] 10 11 12 13 14 15 16 17 18 19 20
> x[x == 15] <- 999
> x
 [1]  10  11  12  13  14 999  16  17  18  19  20

上記を分けて書くと以下のようになる。
※真偽値リストを条件に指定して真である要素を書き換えている。(pandasのデータフレーム等と同じやり方)

> x <- 10:20
> x
 [1] 10 11 12 13 14 15 16 17 18 19 20
> condition <- x == 15
> condition
 [1] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
> x[condition] <- 999
> x
 [1]  10  11  12  13  14 999  16  17  18  19  20

ベクトルの結合

c() でベクトルを結合した別のベクトルを得る事ができる。
※c() の引数に指定したベクトル自体の内容は変わらない。

> x <- 1:10
> y <- 11:20
> z <- c(x, y)
> x
 [1]  1  2  3  4  5  6  7  8  9 10
> y
 [1] 11 12 13 14 15 16 17 18 19 20
> z
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

ベクトルの要素の追加

append を使用するとベクトルに要素を追加した別のベクトルを得る事ができる。
※append の引数に指定したベクトル自体の内容は変わらない。

> x <- 1:10
> y <- append(x, 101:105)
> x
 [1]  1  2  3  4  5  6  7  8  9 10     # x 自体の内容は変わらない
> y
 [1]   1   2   3   4   5   6   7   8   9  10 101 102 103 104 105

行列の操作

行列の生成

matrix で行列を生成する事ができる。

> matrix(1:9, nrow=3, ncol=3)
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> matrix(1:9, nrow=3, ncol=3, byrow=T)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

行数/列数の確認

> x <- matrix(1:10, nrow=2, ncol=5, byrow=T)
> nrow(x)    # 行数の確認
[1] 2
> ncol(x)    # 列数の確認
[1] 5
> dim(x)    # 行数、列数の確認
[1] 2 5

列ラベル/行ラベルの付与

colnames、rownames で列 及び 行にラベルを付与する事ができ、
行/列番号だけでなく、ラベルを指定して要素にアクセスする事ができる。

> x <- matrix(1:20, ncol=5)
> x
     [,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
> colnames(x) <- paste("col", 1:ncol(x), sep="")     # 列にラベルを付与
> x
     col1 col2 col3 col4 col5
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> rownames(x) <- paste("row", 1:nrow(x), sep="")    # 行にラベルを付与
> x
     col1 col2 col3 col4 col5
row1    1    5    9   13   17
row2    2    6   10   14   18
row3    3    7   11   15   19
row4    4    8   12   16   20
> x["row3","col3"]    # 行 及び 列ラベルを指定してアクセス
[1] 11
> x["row3",]              # 行ラベルのみを指定してアクセス
col1 col2 col3 col4 col5 
   3    7   11   15   19 
> x[,"col5"]               # 列ラベルのみを指定してアクセス
row1 row2 row3 row4 
  17   18   19   20

行列の入れ替え

t() で行列を入れ替える事ができる。

> x <- matrix(1:9, nrow=3, ncol=3)
> x
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> t(x)
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

行列の要素へのアクセス

行列の各要素へは [行No, 列No] でアクセス可能。

> x <- matrix(1:9, nrow=3, ncol=3, byrow=T)
> x
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
> x[2,2]
[1] 5
> x[2,2] <- 10
> x
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4   10    6
[3,]    7    8    9

以下のように、特定の値を変更する事も可能。

> x <- matrix(1:9, nrow=3, ncol=3, byrow=T)
> x
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
> x[x == 1 | x == 8] <- 999
> x
     [,1] [,2] [,3]
[1,]  999    2    3
[2,]    4    5    6
[3,]    7  999    9

以下の例では偶数値を "even!" に書き換えている。

> x <- matrix(1:9, nrow=3, ncol=3, byrow=T)
> x
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
> x[x %% 2 == 0] <- "even!"
> x
     [,1]    [,2]    [,3]   
[1,] "1"     "even!" "3"    
[2,] "even!" "5"     "even!"
[3,] "7"     "even!" "9"   

pandasのデータフレームと同じ様に Bool値のリストを作って真となるの要素を書き換える事も可能。

> x <- matrix(1:9, nrow=3, ncol=3, byrow=T)
> x
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9
> x[x %% 2 == 0 -> even]
[1] 4 2 8 6
> even
      [,1]  [,2]  [,3]
[1,] FALSE  TRUE FALSE
[2,]  TRUE FALSE  TRUE
[3,] FALSE  TRUE FALSE
> x[even] <- "even!"
> x
     [,1]    [,2]    [,3]   
[1,] "1"     "even!" "3"    
[2,] "even!" "5"     "even!"
[3,] "7"     "even!" "9"

行列の結合

rbind または cbind で行列を結合する事ができる。
※rbindは縦に行を結合、cbind は横に列を結合。

> x = matrix(1:9,ncol = 3, nrow =3)
> y = matrix(11:13, ncol = 3, nrow =1)
> z = matrix(21:23, ncol = 1, nrow =3)
> x
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
> y
     [,1] [,2] [,3]
[1,]   11   12   13
> z
     [,1]
[1,]   21
[2,]   22
[3,]   23
> rbind(x, y)
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
[4,]   11   12   13
> cbind(x, z)
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   21
[2,]    2    5    8   22
[3,]    3    6    9   23

行列の演算

行列の和、差

> x <- matrix(1:4, 2, 2, byrow=T)
> x
     [,1] [,2]
[1,]    1    2
[2,]    3    4
> y <- matrix(1:4, 2, 2, byrow=T)
> y
     [,1] [,2]
[1,]    1    2
[2,]    3    4
> x + y    # 行列の和
     [,1] [,2]
[1,]    2    4
[2,]    6    8
> x - y    # 行列の差
     [,1] [,2]
[1,]    0    0
[2,]    0    0

行列の積

> x <- matrix(1:6, 2, 3, byrow=T)
> x
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
> y <- matrix(1:6, 3, 2, byrow=T)
> y
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6
> x %*% y           # 行列積は %*% で行う(  x * y だと要素毎の乗算になってしまう )
     [,1] [,2]
[1,]   22   28
[2,]   49   64

numpyでの演算結果 とも一致する。

リストの操作

ベクトルや行列などの異なる構造のデータを集めて 1 個のオブジェクトに纏める場合にはリストを使用する。

リストの生成

> x <- 1:10
> y <- 101:110
> list(x, y)
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
 [1] 101 102 103 104 105 106 107 108 109 110

リストの要素へのアクセス

リストの要素には [要素番号] または [[要素番号]] でアクセスする事ができる。
[要素番号] でアクセスした場合の戻り値はリスト、[[要素番号]]でアクセスした場合の戻り値は要素の内容そのものとなる。

> l = list(1,2,3)
> l[1]
[[1]]
[1] 1

> l[[1]]
[1] 1

リストをベクトルに変換する

unlist でリストをベクトルに変換する事ができる。

> l <- list(1,2,3)
> l
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

> unlist(l)
[1] 1 2 3

データフレームの操作

データフレームを使用すると異なる型のデータをまとめて1 つの変数として持つ事ができる。
単純な行列と違い、各行/列はラベルを持ち、ラベル指定による操作が可能。
列のデータ型が異なっていても扱える為、ベクトルやリストをデータフレームに変換することで統計解析がやりやすくなる。

データフレームの生成

データフレームは data.frame(列名=ベクトル, 列名=ベクトル, ... ) の形式で生成する。

> # 行ラベル
> dates   <- c("2018-06","2018-07","2018-08","2018-09","2018-10","2018-11","2018-12")
> 
> # 以下列データ
> chrome  <- c(41.96, 41.9, 42.54, 41.18, 43.11, 44.28, 44.47)
> safari  <- c(31.83, 32.29, 31.91, 34.45, 33.01, 32.54, 31.96)
> ie      <- c(11.5, 11.13, 11.15, 10.43, 10.2, 9.49, 9.21)
> firefox <- c(6.63, 6.43, 6.44, 6.14, 6.2, 6.31, 6.81)
> edge    <- c(4.29, 4.26, 4.23, 4.36, 4.23, 4.14, 4.0)
> 
> # データフレームの生成
> x = data.frame(Chrome=chrome, Safari=safari, IE=ie, Firefox=firefox, Edge=edge)
>
> # 行ラベルを付与
> rownames(x) <- dates
> x
        Chrome Safari    IE Firefox Edge
2018-06  41.96  31.83 11.50    6.63 4.29
2018-07  41.90  32.29 11.13    6.43 4.26
2018-08  42.54  31.91 11.15    6.44 4.23
2018-09  41.18  34.45 10.43    6.14 4.36
2018-10  43.11  33.01 10.20    6.20 4.23
2018-11  44.28  32.54  9.49    6.31 4.14
2018-12  44.47  31.96  9.21    6.81 4.00

データフレームを行列に変換する

as.matrix による変換

> as.matrix(x)
        Chrome Safari    IE Firefox Edge
2018-06  41.96  31.83 11.50    6.63 4.29
2018-07  41.90  32.29 11.13    6.43 4.26
2018-08  42.54  31.91 11.15    6.44 4.23
2018-09  41.18  34.45 10.43    6.14 4.36
2018-10  43.11  33.01 10.20    6.20 4.23
2018-11  44.28  32.54  9.49    6.31 4.14
2018-12  44.47  31.96  9.21    6.81 4.00

さらに matrix を噛ましてラベルを落とす

> matrix(as.matrix(x), nrow(x), ncol(x))
      [,1]  [,2]  [,3] [,4] [,5]
[1,] 41.96 31.83 11.50 6.63 4.29
[2,] 41.90 32.29 11.13 6.43 4.26
[3,] 42.54 31.91 11.15 6.44 4.23
[4,] 41.18 34.45 10.43 6.14 4.36
[5,] 43.11 33.01 10.20 6.20 4.23
[6,] 44.28 32.54  9.49 6.31 4.14
[7,] 44.47 31.96  9.21 6.81 4.00

colnames、rownames に NULL を設定して名前を落とす

> y <- as.matrix(x)
> y
        Chrome Safari    IE Firefox Edge
2018-06  41.96  31.83 11.50    6.63 4.29
2018-07  41.90  32.29 11.13    6.43 4.26
2018-08  42.54  31.91 11.15    6.44 4.23
2018-09  41.18  34.45 10.43    6.14 4.36
2018-10  43.11  33.01 10.20    6.20 4.23
2018-11  44.28  32.54  9.49    6.31 4.14
2018-12  44.47  31.96  9.21    6.81 4.00
> colnames(y) <- NULL
> rownames(y) <- NULL
> y
      [,1]  [,2]  [,3] [,4] [,5]
[1,] 41.96 31.83 11.50 6.63 4.29
[2,] 41.90 32.29 11.13 6.43 4.26
[3,] 42.54 31.91 11.15 6.44 4.23
[4,] 41.18 34.45 10.43 6.14 4.36
[5,] 43.11 33.01 10.20 6.20 4.23
[6,] 44.28 32.54  9.49 6.31 4.14
[7,] 44.47 31.96  9.21 6.81 4.00

データフレームの列にアクセスする

変数名$列名 とする事でデータフレームの特定の列にアクセスできる。

> df = read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
> df
        Chrome Safari    IE Firefox Edge Android
2018-06  41.96  31.83 11.50    6.63 4.29    0.97
2018-07  41.90  32.29 11.13    6.43 4.26    0.90
2018-08  42.54  31.91 11.15    6.44 4.23    0.90
2018-09  41.18  34.45 10.43    6.14 4.36    0.78
2018-10  43.11  33.01 10.20    6.20 4.23    0.69
2018-11  44.28  32.54  9.49    6.31 4.14    0.69
2018-12  44.47  31.96  9.21    6.81 4.00    0.74
> df$Chrome
[1] 41.96 41.90 42.54 41.18 43.11 44.28 44.47

データフレームに列を追加する

元のデータフレームの内容を書き換える場合は ''変数名$列名 <- ベクトル' で追加する。

> df = read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
> df$Desc <- rownames(df)
> df
        Chrome Safari    IE Firefox Edge Android    Desc
2018-06  41.96  31.83 11.50    6.63 4.29    0.97 2018-06
2018-07  41.90  32.29 11.13    6.43 4.26    0.90 2018-07
2018-08  42.54  31.91 11.15    6.44 4.23    0.90 2018-08
2018-09  41.18  34.45 10.43    6.14 4.36    0.78 2018-09
2018-10  43.11  33.01 10.20    6.20 4.23    0.69 2018-10
2018-11  44.28  32.54  9.49    6.31 4.14    0.69 2018-11
2018-12  44.47  31.96  9.21    6.81 4.00    0.74 2018-12

transform を使用するとデータフレームに新たな列を追加した別のデータフレームを得る事ができる。
※元のデータフレームの内容は変わらない。

> df = read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
> df
        Chrome Safari    IE Firefox Edge Android
2018-06  41.96  31.83 11.50    6.63 4.29    0.97
2018-07  41.90  32.29 11.13    6.43 4.26    0.90
2018-08  42.54  31.91 11.15    6.44 4.23    0.90
2018-09  41.18  34.45 10.43    6.14 4.36    0.78
2018-10  43.11  33.01 10.20    6.20 4.23    0.69
2018-11  44.28  32.54  9.49    6.31 4.14    0.69
2018-12  44.47  31.96  9.21    6.81 4.00    0.74
> desc = rownames(df)
> desc
[1] "2018-06" "2018-07" "2018-08" "2018-09" "2018-10" "2018-11" "2018-12"
> df2 = transform(df, Desc=desc)
> df2
        Chrome Safari    IE Firefox Edge Android    Desc
2018-06  41.96  31.83 11.50    6.63 4.29    0.97 2018-06
2018-07  41.90  32.29 11.13    6.43 4.26    0.90 2018-07
2018-08  42.54  31.91 11.15    6.44 4.23    0.90 2018-08
2018-09  41.18  34.45 10.43    6.14 4.36    0.78 2018-09
2018-10  43.11  33.01 10.20    6.20 4.23    0.69 2018-10
2018-11  44.28  32.54  9.49    6.31 4.14    0.69 2018-11
2018-12  44.47  31.96  9.21    6.81 4.00    0.74 2018-12

データフレームに行を追加する

変数名[行ラベル名,] <- データ で行データを追加できる。

> df = read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
> df
        Chrome Safari    IE Firefox Edge Android
2018-06  41.96  31.83 11.50    6.63 4.29    0.97
2018-07  41.90  32.29 11.13    6.43 4.26    0.90
2018-08  42.54  31.91 11.15    6.44 4.23    0.90
2018-09  41.18  34.45 10.43    6.14 4.36    0.78
2018-10  43.11  33.01 10.20    6.20 4.23    0.69
2018-11  44.28  32.54  9.49    6.31 4.14    0.69
2018-12  44.47  31.96  9.21    6.81 4.00    0.74
> df["2019-01",] <- c(42.9, 33.84, 9.45, 6.01, 4.16, 0.7)
> df
        Chrome Safari    IE Firefox Edge Android
2018-06  41.96  31.83 11.50    6.63 4.29    0.97
2018-07  41.90  32.29 11.13    6.43 4.26    0.90
2018-08  42.54  31.91 11.15    6.44 4.23    0.90
2018-09  41.18  34.45 10.43    6.14 4.36    0.78
2018-10  43.11  33.01 10.20    6.20 4.23    0.69
2018-11  44.28  32.54  9.49    6.31 4.14    0.69
2018-12  44.47  31.96  9.21    6.81 4.00    0.74
2019-01  42.90  33.84  9.45    6.01 4.16    0.70

ラベル名が不要(もしくは連番) の場合は、変数名[nrow(変数名)+1,] <- データ でOK。

> df = read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
> rownames(df) <- NULL  # 行ラベルを落とす
> df
  Chrome Safari    IE Firefox Edge Android
1  41.96  31.83 11.50    6.63 4.29    0.97
2  41.90  32.29 11.13    6.43 4.26    0.90
3  42.54  31.91 11.15    6.44 4.23    0.90
4  41.18  34.45 10.43    6.14 4.36    0.78
5  43.11  33.01 10.20    6.20 4.23    0.69
6  44.28  32.54  9.49    6.31 4.14    0.69
7  44.47  31.96  9.21    6.81 4.00    0.74
> df[nrow(df)+1,] <- c(42.9, 33.84, 9.45, 6.01, 4.16, 0.7)
> df
  Chrome Safari    IE Firefox Edge Android
1  41.96  31.83 11.50    6.63 4.29    0.97
2  41.90  32.29 11.13    6.43 4.26    0.90
3  42.54  31.91 11.15    6.44 4.23    0.90
4  41.18  34.45 10.43    6.14 4.36    0.78
5  43.11  33.01 10.20    6.20 4.23    0.69
6  44.28  32.54  9.49    6.31 4.14    0.69
7  44.47  31.96  9.21    6.81 4.00    0.74
8  42.90  33.84  9.45    6.01 4.16    0.70

データフレームで使用できる分析関数

TODO:

ファイル操作

writeによるファイル出力

以下、行列をファイルに出力する例を記載する。

> x <- matrix(1:10, ncol=2)
> x
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10
> write(x, file="data_matrix.txt", ncolumns=2)

結果は転置されて出力される。

(結果)

1 2
3 4
5 6
7 8
9 10

転置せずに出力する場合は、事前に t で転置してから出力する。

> write(t(x), file="data_matrix.txt", ncolumns=2)

(結果)

1 6
2 7
3 8
4 9
5 10

scan によるファイル読み込み

scan でファイルのデータをベクトルとして読み込む事ができる。

> x <- matrix(1:10, ncol=5, byrow=T)
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10
> write(x, "test_matrix.txt")
> y <- scan("test_matrix.txt")
Read 10 items
> y
 [1]  1  6  2  7  3  8  4  9  5 10

結果はベクトルになるので行列に変換する場合は matrix で自分で変換する。

> matrix(y, ncol=5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    6    7    8    9   10

データ型が混在する場合はデータ型を明示しないとエラーになる。( what に列毎のデータ型 または 変換関数のリストを指定する )

x = data.frame(Name=c("Yamada", "Tanaka"), Age=c(20, 22), Sex=c("M","W"))
write.table(x, "output.csv", quote=F, col.names=T, row.names=F, sep=",")
system("cat output.csv")
> system("cat output.csv")
Name,Age,Sex
Yamada,20,M
Tanaka,22,W
> scan("output.csv", skip=1, sep=",")
 scan("output.csv", skip = 1, sep = ",") でエラー: 
   scan() 関数は 'a real' を期待したのに、得られたのは 'Yamada' でした 
> scan("output.csv", what=list("",numeric(),""), skip=1, sep=",")
Read 2 records
[[1]]
[1] "Yamada" "Tanaka"

[[2]]
[1] 20 22

[[3]]
[1] "M" "W"

writeLines によるテキストファイル出力

writeLines でテキストデータをファイルに出力する事ができる。

> con = file("sample.txt", open="w")
> writeLines("This is Sample!", con)
> writeLines("Hello R!!", con)
> writeLines("This is 3rd Line.", con)
> close(con)
> 
> system("cat sample.txt")
This is Sample!
Hello R!!
This is 3rd Line.

cat に file オプションと sep オプションを指定しても同じ事ができる。

> con = file("sample.txt", open="w")
> cat("This is Sample!", "Hello R!!", "This is 3rd Line.", file=con, sep = "\n")
> close(con)
> 
> system("cat sample.txt")
This is Sample!
Hello R!!
This is 3rd Line.

readLines によるテキストファイルの読み込み

readLines ではファイルから1行=1要素としたベクトルを得る事ができる。

sample.txt

This is  first  Line.
Hello R!

読み込み例

> x =  readLines('sample.txt')
> x
[1] "This is  first  Line." "Hello R!"             
> x[1]
[1] "This is  first  Line."
> x[2]
[1] "Hello R!"

csvファイルの入出力

read.table で csvファイルからデータフレームを生成できる。

browser-JP.csv ( http://gs.statcounter.com/browser-market-share/all/japan より )

"Date","Chrome","Safari","IE","Firefox","Edge","Android"
2018-06,41.96,31.83,11.5,6.63,4.29,0.97
2018-07,41.9,32.29,11.13,6.43,4.26,0.9
2018-08,42.54,31.91,11.15,6.44,4.23,0.9
2018-09,41.18,34.45,10.43,6.14,4.36,0.78
2018-10,43.11,33.01,10.2,6.2,4.23,0.69
2018-11,44.28,32.54,9.49,6.31,4.14,0.69
2018-12,44.47,31.96,9.21,6.81,4,0.74

読み込み例

> read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
        Chrome Safari    IE Firefox Edge Android
2018-06  41.96  31.83 11.50    6.63 4.29    0.97
2018-07  41.90  32.29 11.13    6.43 4.26    0.90
2018-08  42.54  31.91 11.15    6.44 4.23    0.90
2018-09  41.18  34.45 10.43    6.14 4.36    0.78
2018-10  43.11  33.01 10.20    6.20 4.23    0.69
2018-11  44.28  32.54  9.49    6.31 4.14    0.69
2018-12  44.47  31.96  9.21    6.81 4.00    0.74

※sep="," で 列の区切り文字を指定している。
※header=T で1行目は列名である事を示している。
※row.names で行ラベルに使用する列名を指定している。(上記では "Date" 列のデータを行ラベルとして扱う旨を示している)
※詳細は ?read.table で確認。

write.table でデータフレームをCSVファイルに出力できる。

> write.table(x, "output.csv", quote=F, col.names=T, row.names=T, sep=",")

※詳細は ?write.table で確認。

Excelへのデータ出力

インストール

install.packages("xlsx")
install.packages('rJava')

手元のMacではインストール時に以下のエラーを吐いてコケる。

 警告メッセージ: 
 doTryCatch(return(expr), name, parentenv, handler) で: 
   共有ライブラリ '/Library/Frameworks/R.framework/Resources/modules//R_X11.so' を読み込めません: 
  dlopen(/Library/Frameworks/R.framework/Resources/modules//R_X11.so, 6): Library not loaded: /opt/X11/lib/libcairo.2.dylib
  Referenced from: /Library/Frameworks/R.framework/Resources/modules//R_X11.so
  Reason: Incompatible library version: R_X11.so requires version 11403.0.0 or later, but libcairo.2.dylib provides version 11203.0.0 

R_X11.so のバージョンが古いらしいので https://github.com/satijalab/seurat/issues/299 を参考に、以下の通り対応。

brew cask install xquartz

実際に使おうとすると、今度は以下のエラーになる。

> library(xlsx)
 エラー: package or namespace load failed for ‘xlsx’:
  .onLoad は loadNamespace()('rJava' に対する)の中で失敗しました、詳細は: 
  call: dyn.load(file, DLLpath = DLLpath, ...) 
  error:  共有ライブラリ '/Library/Frameworks/R.framework/Versions/3.5/Resources/library/rJava/libs/rJava.so' を読み込めません: 
  dlopen(/Library/Frameworks/R.framework/Versions/3.5/Resources/library/rJava/libs/rJava.so, 6): Library not loaded: /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/lib/server/libjvm.dylib
  Referenced from: /Library/Frameworks/R.framework/Versions/3.5/Resources/library/rJava/libs/rJava.so
  Reason: image not found  

どうもインストールされていないJDKのバージョンのものを探してる模様。
解決方法を調べてみると dyn.load("/path/to/libjvm.dylib") で libjvm.dylib の場所を指定する方法や /usr/local/lib/ にシンボリックリンクを貼る方法等が見つかったが、
ここでは素直に jdk11 をインストールした。( Java11から商用利用は有償になるので corretto とかの方が良いかも )
https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-5066655.html

library(xlsx)
x = read.table("browser-JP.csv", sep=",", header=T, row.names="Date")
write.xlsx(x, "output.xlsx", sheetName="Sheet1", col.names=TRUE, row.names=TRUE, append=FALSE, showNA=TRUE, password=NULL)

https://www.rdocumentation.org/packages/xlsx/versions/0.6.1/topics/write.xlsx

オブジェクトの保存と読み込み

R ではオブジェクトそのものをファイルに保存したり、ファイルから復元する事ができる。

ベクトル x をファイルに保存)

> x <- 1:10
> x
 [1]  1  2  3  4  5  6  7  8  9 10
> save(x, file="x.rdata")

いちど変数を削除後にファイルから x を読み込む)

> rm(x)
> x
 エラー:  オブジェクト 'x' がありません 
> load("x.rdata")
> x
 [1]  1  2  3  4  5  6  7  8  9 10

ファイル一覧の取得

list.files("/tmp", full.names = F)

※結果はlist

applyファミリー

他の言語の map や apply 等と同様に R にも行列やデータフレームの各要素に対して関数を適用する仕組みがある。
※Rのループは遅いので繰り返し処理の内容を関数化しておいて apply する等の用途でも利用される。

apply

apply は行列やデータフレームの各要素に関数を適用する。

形式)

apply(X, MARGIN, FUN, ...)

引数)

引数説明
Xデータフレーム または 行列を指定する
MARGIN行に対して処理する場合は 1 、列に対して処理する場合は 2 、両方に対して処理する場合は c(1,2) を指定する
FUN適用する関数を指定する

利用例1)

> x = data.frame(col1=c(1,2,3,4,5), col2=c(6,7,8,9,10), col3=c(11,12,13,14,15))
> x
  col1 col2 col3
1    1    6   11
2    2    7   12
3    3    8   13
4    4    9   14
5    5   10   15
> apply(x, 1, sum)    # 行毎の合計
[1] 18 21 24 27 30
> apply(x, 2, sum)    # 列毎の合計
col1 col2 col3
  15   40   65

利用例2)

> myfunc <- function(x){
+     return (x*2)
+ }
> apply(x, 1:2, myfunc)
     col1 col2 col3
[1,]    2   12   22
[2,]    4   14   24
[3,]    6   16   26
[4,]    8   18   28
[5,]   10   20   30

lapply

リストに関数を適用しリストを返却する。

TODO:

sapply

リストに関数を適用しベクトル または 行列を返す。

TODO:

tapply

グループ化されたデータについてグループ毎に関数を適用する。

形式)

tapply(X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)

引数)

引数説明
Xデータフレーム または 行列を指定する
INDEXグループ分けに使用するデータを リスト または factor で指定する ( 因子型(factor) )
FUN適用する関数を指定する

利用例)

> name <- c("Yamada", "Tanaka", "Sato", "Suzuki", "Yamamoto", "Takahashi", "Kobayashi", "Kato", "Ito", "Watanabe")
> sex <- c("W", "M", "M", "M", "W", "W", "W", "W", "M", "W")
> state <- c("Osaka", "Tokyo", "Osaka", "Osaka", "Nagoya", "Osaka", "Tokyo", "Tokyo", "Nagoya", "Tokyo")
> height <- c(170.5, 175.4, 171.2, 173.6, 169.8, 165.2, 178.1, 165.5, 173.2, 172.9)
> 
> x <- data.frame(Name=name, Sex=sex, State=state, Height=height)
> 
> # 都道府県ごとの平均身長
> tapply(x$Height, list(x$State), mean)
 Nagoya   Osaka   Tokyo 
171.500 170.125 172.975 
> 
> # 男女毎の平均身長
> tapply(x$Height, list(x$Sex), mean)    # INDEXには tapply(x$Height, factor(x$Sex), mean)  で factor を指定してもOK
       M        W 
173.3500 170.3333 
> 
> # 都道府県、男女毎の平均身長
> tapply(x$Height, list(x$State, x$Sex), mean)
           M        W
Nagoya 173.2 169.8000
Osaka  172.4 167.8500
Tokyo  175.4 172.1667

mapply

TODO:

乱数の生成

乱数の生成を行う為の関数が豊富に用意されている。

正規分布

例)身長データを100個生成する。(平均値は 170、標準偏差は 10とする)

> x = rnorm(100, mean = 170, sd = 10)    # 乱数の生成
> round(x, digits = 1)                                 # 小数点以下1桁になるように四捨五入
  [1] 164.3 180.4 182.8 190.1 154.7 177.2 168.7 167.2 160.9 177.9 168.2 173.4 168.7 177.5 166.9 163.7 174.2 153.8
 [19] 187.5 164.4 154.6 172.6 175.1 181.1 184.3 148.7 172.7 160.8 149.0 163.7 184.1 162.7 161.8 183.5 171.8 177.9
 [37] 164.6 170.1 165.5 182.7 178.2 171.7 156.0 177.9 174.0 186.0 153.5 176.4 183.5 166.2 179.9 174.1 146.0 159.1
 [55] 169.1 163.7 172.6 165.2 171.3 184.8 177.0 181.6 164.6 154.1 178.9 175.7 170.1 155.8 161.9 153.9 186.8 184.9
 [73] 170.0 176.7 166.7 166.5 177.8 179.4 169.6 179.1 177.6 169.7 175.8 151.1 178.9 183.6 158.3 172.0 149.6 162.6
 [91] 158.6 153.6 180.5 177.6 168.4 163.0 171.2 159.9 156.3 173.2

XXXXXXXXXX

TODO:

因子型(factor)

因子型の概要

TODO:

因子型の利用例

TODO: tapplyでの利用例

分析関数

TODO:

回帰分析


トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS