Rのパッケージのインストール

R では「パッケージ」を使って,計算や可視化に便利な機能を追加することができます.社会基盤計画学演習では,線形計画法を解くためのパッケージ「lpSolve」を使います.

1. パッケージのインストール

(1) メニューバーから「パッケージ(packages)」を選択します.

(2)「CRAN ミラーサイトの設定」を選択し,適当な国・機関のミラーサイトを選びます.

(3) 「パッケージの一覧」をクリックし、パッケージ一覧から「lpSolve」を選び,ダウンロードします.以下のような画面が出たらインストール成功です。

※Rには多くの便利なパッケージがあります.例えば「ggplot2」というパッケージではきれいなグラフなどを作成することが出来ます.

2. ライブラリのロード

インストールしたパッケージを利用するには,ライブラリをロードする必要があります.R エディタ上に下記のコードを入力し,そのコードの行頭にカーソルをあてて「Ctrl+R」で実行します.

library(lpSolve)

これで,「lpSolve」ライブラリを使えるようになります.

社会基盤計画学演習 R基礎演習1

内容

0. Rstudioでプログラムを入力,実行する方法

1.タブ左上の「ファイル」→「新しいスクリプト」をクリックすると,エディタ(入力するコマンドを書く場所)が開く.※既に,演習用スクリプトを作成している場合は,この操作は不要です.

2.何かプログラムを入力したら,実行したいコマンドの右側にカーソルを置いて,「Ctrl」+「R」で実行する.もしくは,実行したいコマンドをマウスなどで範囲選択し,「編集」→「カーソル行または選択中のRコードを実行」でも同様の操作ができる.

3. 適宜,プログラムを書いたら「Ctrl」+「S」でファイルを保存すること.

4. 「#」を行頭に入れると,それはコマンドではなく「コメント」として扱われる.これを「コメントアウト」という.後で自分が思い出す場合や,人に渡したときにわかりやすくなるので,積極的に使っていこう.

1. 四則演算

主な演算子は以下の通りです(参考).基本的には,多くのプログラミング言語で使われている演算子と同じです.

演算の種類Rで入力する演算子入力例
足し算+7+17
引き算17-4
かけ算*17*28
割り算/8/4
累乗^0.9^4

例1:以下の四則演算を実行し,計算結果が出るかどうか確かめてください.

7+17
17-4
17*28
28/4
0.9^4

2. オブジェクトと代入(付値)

オブジェクトとは,変数,数の配列,文字列関数,データ,関数など,R 上で生成され,扱われる実体のことです.オブジェクト名は自由に決められますが,「予約語」と呼ばれるあらかじめ決められたキーワードは使えません.大文字と小文字は区別されるので注意しましょう.オブジェクトに何らかの具体的な値を与える操作のことを「付値」「代入」とよび,以下の代入演算子を用いて操作します.表は,全てxに2という代入を付値する例で,どれも同じ操作を意味します.

演算子説明
<-x <- 2右辺の値を左のオブジェクトに代入
->2 -> x左辺の値を右のオブジェクトに代入
=x = 2右辺の値を左のオブジェクトに代入
assign(“変数名”,値)assign(“x”,2)“変数名”に値を代入
xに2という数値を付値する例.どれも同じ操作を意味します.

例2:オブジェクト名「eip」に以下の計算結果を代入せよ.また,代入した結果を見るため「eip」というオブジェクト名を入力して,実行せよ.

\(\frac{10^2 + 7}{1+(2 \times 3)}\)
#計算結果の代入
eip <-((10^2)+7)/(1+(2*3))
((10^2)+7)/(1+(2*3)) -> eip
eip =((10^2)+7)/(1+(2*3))
assign("eip",((10^2)+7)/(1+(2*3)))

#eipの中身を見る
eip

3. ベクトルの生成と操作

実数,複素数,文字列,論理数などに対し,同じ型のデータをいくつかまとめたものを「ベクトル」と呼びます.ベクトルの中の数を「要素」と呼び,各要素には左から順に1, 2, ・・・と番号が振られています.ベクトルは⻑さを持ちます.⻑さとは,一つのベクトルに含まれる要素(データ)の数です.ベクトルを作成する関数はc() ですが,その他にrep() やseq() などの関数もあります.

また,ベクトルの要素は,integer(整数型),logical(論理型),character(文字列型)など,様々な形式を取ることができる.ただし,ベクトルの場合はすべての要素が同じ型でなければならない.

関数説明
c()c(1.0, 2.0, 3.0, 4.0, 5.0)⻑さ5 のベクトルを作る
seq()seq(1, 10, length=5)1 から10 までを等分割した⻑さ5 のベクトルを作る
rep()rep(1:3, length=8)数列(1 2 3) を⻑さ8 になるまで反復生成
ベクトルを生成する関数

例3-1:4と5の二つの要素からなるベクトルを作成し,オブジェクト「e1」に代入せよ.

e1 <- c(4,5)
e1

例3-2:「愛知」「三重」「岐阜」「静岡」からなるベクトルを作成し,オブジェクト「e2」に代入せよ.※要素が「文字列」のときは,要素を「” “」でくくる必要がある.

e2 <- c("愛知","三重","岐阜","静岡")
e2

4. 行列の生成と操作

行と列を持つオブジェクトとして,「行列」と「データフレーム」があります.行列は,すべての要素が同じ型でなければなりませんが,データフレームの場合は,文字列や整数,実数などのデータ型をそのまま保持します.今回の演習では「行列」のみ扱います.行列を生成する方法は主に二つあります.

4-1. 関数matrix() を使う方法

第一引数に要素を表すベクトル,nrow で行数,ncol で列数を指定する.

例4-1:以下の行列をmatrix()関数を用いて作成せよ.

\(\begin{pmatrix}
1 & 2 \\
3 & 4
\end{pmatrix}\)
matrix(c(1:4), nrow=2, ncol=2)

4-2. 複数のベクトルを,関数rbind() あるいはcbind() で結合させる方法

行ベクトル単位で結合する場合は関数rbind() を使う.また,列ベクトル単位で結合する場合は関数cbind() を使う.

例4-2:以下の行列をrbind()関数とcbind()関数を用いて,それぞれ作成せよ.

\(\begin{pmatrix}
1 & 2 & 3 & 4 \\
1 & 2 & 3 & 4
\end{pmatrix}\)

\(\begin{pmatrix}
1 & 1 \\
2 & 2 \\
3 & 3 \\
4 & 4 \\
\end{pmatrix}\)
rbind(c(1:4),c(1:4)) ♯ 行ベクトル単位
cbind(c(1:4),c(1:4)) ♯ 列ベクトル単位

5. 線形計画法

5-1. 線形計画問題を解くことのできるパッケージ lpSolveの導入

Rでは,上記で使用した標準で用意されている関数の他に,他の誰かが開発して公開している関数を使うことが出来ます.関数を含む一つのまとまりを「パッケージ」といいます.Rには,CRANというパッケージのリポジトリ(保管庫)があり,そこからダウンロードして使うことが出来ます.

今回は,線形計画問題を解くことのできるパッケージ 「lpSolve」を使います.このパッケージの詳細はこちらのドキュメントを参照してください.

パッケージをダウンロード,インストールするには install.packages()という関数を使います.以下のコマンドを実行します.【注意!】このコマンドは一度実行したら,再度実行する必要はありません.ただし,今後Rをパソコンに再インストールしたり,Cloud版のアカウントを作り直した場合は再度実行の必要があります.

install.packages("lpSolve")

Rでは,パッケージはインストールするだけでは使えません.パッケージは,パッケージ名を引数とする関数library(パッケージ名)を実行することで使えるようになります.【注意!】このコマンドは,Rを再起動するたびに毎回実行する必要があります.

library(lpSolve)

まず,以下の演習問題を解いてみよう.

\(
\begin{eqnarray*}
f=29x_1+45x_2\to\mbox{max}
\end{eqnarray*} \\
\)

\(
s.t. \left\{
\begin{array}{llll}
2x_1& +8x_2 & \leq 60\\
4x_1& +4x_2 & \leq 60\\
\end{array}
\right.
\)

\(
\begin{eqnarray*}
x_1 \geq 0, x_2 \geq0
\end{eqnarray*}
\)

5-1. データの作成

まず,データを作成する.ここで,データとは,目的関数の係数や,制約条件に使う外生変数(パラメータ)のことである.1行目では,目的関数の係数のベクトルを作成し「fobj」というオブジェクトに付値している.2行目では,制約条件のベクトル$A$を作成し「fconst」というオブジェクトに付値している.3行目では,制約条件式の不等号を文字列型を要素としたベクトルで指定し「fdir」というオブジェクトに付値している(他の不等号の種類についてはこちらのウェブサイトなどを参照のこと).4行目では,制約条件式の右辺の値bのベクトルを指定し「rrhs」というオブジェクトに付値している.

fobj <- c(29,45)
fconst <- matrix(c(2,8,4,4),ncol=2,byrow = T)
fdir <- c("<=","<=")
rrhs <- c(60,60)

5-2. 線形計画問題の実行

関数lp()に引数を与える.また,その結果を「result」というオブジェクトに与えた.解説はコメントアウトに記載した.なお,各変数の非負制約は前提となっているため,ここで指定する必要はない.

result <- lp("max", # 最大化問題
             fobj, # 目的関数の係数c(numeric型の要素からなるベクトル)
             fconst, # 制約条件式の左辺の係数の行列A (numeric型の要素からなるmatrix)
             fdir, # character型の要素からなるベクトル
             rrhs, # 制約条件式の右辺のベクトルb (numeric型の要素からなるmatrix)
             compute.sens=T ) # 感度分析を行うか

結果を見るにはresultをそのまま入力してもよいが,Rが表示するのは目的関数の最適値のみである.

result

実は,resultはリスト型のオブジェクトである.リスト型とは,これら異なる構造のデータを集めて 1 個のオブジェクトにしたものである.resultの中にはもっと詳しい結果が入っており,それらを見ることもできる.

以下のようにnames(リスト型のオブジェクト名)を実行すると,リストが含んでいる要素の名前一覧が出てくる.

names(result)

ここに出てきている要素名を使って,以下のように指定すると,特定のリスト要素の中身を見ることが出来る.以下は,最適解を表示したものである.

result$solution

以下は,目的関数の最適値を示したものである.

result$objval

5-2. 結果の可視化

上記で得られた最適解を,棒グラフを使って可視化してみよう.例として,都市における人口の配分の問題とみた場合のラベルをグラフに付与している.

paste関数は,与えられた引数を文字列としてつなげるものである.研究レベルでは非常によく使うものである.詳しくはこちらを参照のこと.

length関数は,与えられた引数の要素の数を返す関数である.

barplot(result$solution, # 最適解が入ったベクトル
        names.arg=paste("地域", c(1:length(result$solution))), #x軸のラベル
        main = "最適解における都市の人口配分", #グラフの上部のタイトル
        xlab = "地域名", #x軸のタイトル
        ylab = "人口[万人]" #y軸のタイトル
        )

Rの基本的な操作

Rでプログラムを入力,実行する方法

何かプログラムを入力したら(例:1+1),以下のように実行したいプログラムの右側にカーソルを置いて,「Ctrl」+「R」で実行する.

四則演算

 主な演算子は以下の通りです(参考).基本的には,多くのプログラミング言語で使われている演算子と同じです.

演算の種類Rで入力する演算子入力例
足し算+7+17
引き算17-4
かけ算*17*28
割り算/8/4
累乗^.9^4

問1:以下の四則演算を実行し,計算結果が出るかどうか確かめてください.

7+17
17-4
17*28
28/4
0.9^4

オブジェクトと代入(付値)

 オブジェクトとは,変数,数の配列,文字列関数,データ,関数など,R 上で生成され,扱われる実体のことです.オブジェクト名は自由に決められますが,「予約語」と呼ばれるあらかじめ決められたキーワードは使えません.大文字と小文字は区別されるので注意しましょう.オブジェクトに何らかの具体的な値を与える操作のことを「付値」「代入」とよび,以下の代入演算子を用いて操作します.表は,全てxに2という代入を付値する例で,どれも同じ操作を意味します.

演算子説明
<-x <- 2右辺の値を左のオブジェクトに代入
->2 -> x左辺の値を右のオブジェクトに代入
=x = 2右辺の値を左のオブジェクトに代入
assign(“変数名”,値)assign(“x”,2)“変数名”に値を代入
xに2という数値を付値する例.どれも同じ操作を意味します.

問2:オブジェクト名「eip」に以下の計算結果を代入せよ.また,代入した結果を見るため「eip」というオブジェクト名を入力して,実行せよ.

\(\frac{10^2 + 7}{1+(2 \times 3)}\)
#計算結果の代入
eip <-((10^2)+7)/(1+(2*3))
((10^2)+7)/(1+(2*3)) -> eip
eip =((10^2)+7)/(1+(2*3))
assign("eip",((10^2)+7)/(1+(2*3)))

#eipの中身を見る
eip

ベクトルの生成と操作

実数,複素数,文字列,論理数などに対し,同じ型のデータをいくつかまとめたものを「ベクトル」と呼びます.ベクトルの中の数を「要素」と呼び,各要素には左から順に1, 2, ・・・と番号が振られています.ベクトルは⻑さを持ちます.⻑さとは,一つのベクトルに含まれる要素(データ)の数です.ベクトルを作成する関数はc() ですが,その他にrep() やseq() などの関数もあります.

関数説明
c()c(1.0, 2.0, 3.0, 4.0, 5.0)⻑さ5 のベクトルを作る
seq()seq(1, 10, length=5)1 から10 までを等分割した⻑さ5 のベクトルを作る
rep()rep(1:3, length=8)数列(1 2 3) を⻑さ8 になるまで反復生成
ベクトルを生成する関数

問3:4と5の二つの要素からなるベクトルを作成し,オブジェクト「e1」に代入せよ.

e1 <- c(4,5)
e1

重回帰分析

最小二乗法による重回帰パラメータの算出

  • read.csv関数を使って,以下のURLのデータを読み込み,オブジェクト「S16」に代入(付値)するプログラムを書け.
    • https://fnakai.web.nitech.ac.jp/data/14_LP/16Students.csv
  • sum関数を用いて\(\sum x, \sum y, \sum z, \sum x^2, \sum z^2,\sum xy,\sum xz,\sum zy\)を求めよ.
  • 重回帰パラメータを導出する正規方程式に,上記の値を当てはめた連立方程式を書け(解かなくて良い).
  • lm関数を使ってパラメータ\(a,b,c\)を求め,回帰式を書け.

sum関数について

以下を実行してみてほしい.sum関数は,sum( )の括弧の中にベクトルを入れると,その成分の和を返すことがわかる.

a <- c(1,1,1,1,1,1)
sum(a)

以下を実行してみてほしい.「*」はかけ算の演算子である.また,S16$Weight[i]は,Weightのi番目の成分を意味する.ベクトル同士に対して「*」によるかけ算をおこなうことで,どのような演算結果が返されるか?

S16$Weight * S16$Height
S16$Weight[1] * S16$Height[1]

lm関数について

lm関数は,回帰モデルを求める関数である.以下のformulaでは回帰モデルの形を指定する.formulaにはいくつかの種類があるので,以下のWebサイトを参考にしてほしい.

参考ウェブサイト:回帰分析と重回帰分析

formulaを「y ~ x」と指定することで,モデル式 \(y = a + bx + \epsilon\)( \(\epsilon\)は誤差項)の回帰モデルを求めることができる.被説明変数 y と説明変数 x は,ベクトルで指定する.

lm(formula)

たとえば,以下は体重を被説明変数,身長を説明変数とした場合である.

lm(S16$Weight~S16$Height)

formulaを「y ~ x+z」と指定することで,モデル式 \(y = a + bx + cz + \epsilon\)の回帰モデルを求めることができる.

◆レポート提出課題(全10問)

1.read.csv関数を使って,以下のURLのデータを読み込み,オブジェクト「S16」に代入(付値)するプログラムを示しなさい.

2.「*」はかけ算の演算子である.ベクトル同士に対して「*」によるかけ算をおこなうことで,どのような演算結果が返されるか?以下を実行することにより,考察せよ.

S16$Weight * S16$Height
S16$Weight[1] * S16$Height[1]
S16$Weight[2] * S16$Height[2]

3.sum関数を用いて\(\sum x, \sum y, \sum z, \sum x^2, \sum z^2,\sum xy,\sum xz,\sum zy\)を求めるプログラムを示しなさい.

4.重回帰パラメータを導出する正規方程式に,上記の値を当てはめた連立方程式を書け(解かなくて良い).

5.lm関数を用いて,被説明変数に「身長」を,説明変数に「体重」と「胸囲」を置いた重回帰モデルを作成せよ.また,パラメータa,b,cを明示したうえで,重回帰式を示せ.

6.lm関数の結果をオブジェクト「result」に代入(付値)するプログラムを示しなさい.

7.summary(result)を実行せよ.また,以下の表を参考に,結果について以下の点を考察せよ.

  • モデル式とデータの入力情報について日本語で説明せよ.
  • 残差とは,回帰式と実データによって求められる偏差\(y_i – \overline{y}_{xz}\)のことである.その要約統計量を示しているのが,Residualsである.これより,残差についてわかることや,気が付いたことを説明せよ.
  • 重決定係数の値を求めよ.また,sqrt関数を用いることにより,重相関係数を求めよ(sqrt関数については「?sqrt」と入力して,ヘルプを見ること).
R上の表記説明
Call:モデル式とデータの入力情報.
Residuals:残差の四分位数に関する情報.
Coefficients:Estimate: 回帰係数の推計値\(\overline{y}_{xz}\)
Std. Error:回帰係数の標準誤差
t value:回帰係数t値.推定値と標準誤差の比.
Pr(>|t|):回帰係数のp値.
Residual standard error:残差の標準誤差.誤差項の標準偏差の推定値.
Multiple R-squared:決定係数(※通常の/演習でもとめている決定係数のこと)
Adjusted R-squared:自由度調整済み決定係数
F-statistic:F 値.回帰式が意味があるかどうかを検定する統計量。

p-value:
(F 検定に基づく)p 値.回帰式が意味が無い(全ての説明変数の係数がゼロである)確率
summary(result)の結果の読み取り方

8.lm関数を用いて,被説明変数に「身長」を,説明変数に「体重」のみを置いた単回帰モデルを作成せよ.この結果は「result2」に代入せよ.また,パラメータa,bを明示したうえで,単回帰式を示せ.

9.8の単回帰モデルについて,summary(result2)を実行することにより,重回帰分析の時と同様に結果を考察せよ.

10.単回帰モデルの結果と重回帰モデルのsummary関数の実行結果をもとに結果の比較を行い,どちらのほうが「身長」をよく説明するモデルか,考察せよ.

◆レポートの作成方法と提出方法

作成方法

  • wordファイルで作成すること.
  • 以下の内容を必ず含むこと
    • 講義名,学籍番号,名前,提出日
    • 問の番号と問の内容,解答
    • 図を貼りつける場合,図の番号と図のキャプション

提出方法

  • moodle上で以下2点を提出すること.
    • wordファイル
    • 課題を解く際に作成したRのプログラム

自転車駐輪場の利用利用金収入額と駅の平均乗降客数の分析

教科書p.60[事例5-b]の分析

回帰式を求め,データと共に描画します.

これを描くRのコードは以下です.

# coded by F.Nakai
# 2021.01.20

#データの読み込み
SIU <- read.csv("https://fnakai.web.nitech.ac.jp/data/13_LP/StationIncomeAndUsers.csv")

#Rのlm関数による回帰パラメータの導出
result <- lm(SIU$Income~SIU$UsersNum)
result

##問2 手計算の過程の再現
#yの偏差
yy <- (SIU$Income-mean(SIU$Income))
#xの偏差
xx <- (SIU$UsersNum-mean(SIU$UsersNum))

#xの分散とxとyの共分散を求める
Sxy <- sum(xx*yy)*(1/length(xx))
Sxx <- sum(xx^2)*(1/length(xx))

# b=(xとyの共分散/xの分散)
b <- Sxy/Sxx

# a= (yの平均)-b*(xの平均) 
a <- (mean(SIU$Income))-(b*mean(SIU$UsersNum))

#教科書p.61の図を描く
plot(SIU$UsersNum,SIU$Income,
     xlim = c(0,300),
     ylim = c(0,250),
     main = "自転車駐輪場の利用利用金収入額と駅の平均乗降客数",
     xlab = "駅の平均乗降客数(百人/日)",
     ylab = "自転車駐輪場の利用料金収入額(万円/月)"
)

#回帰直線を重ねる
abline(a = a, b = b)

##発展編:きれいに図を描くggplotパッケージの利用

#パッケージのインストール
install.packages("ggplot2")
install.packages("ggpmisc")

#パッケージの読み込み
library(ggplot2)
library(ggpmisc)

#回帰のモデル式を保存しておく
my.formula <- y ~ x

#図を描く
ggplot(data = SIU, mapping = aes(x = UsersNum, y = Income)) +
  geom_point() +
  labs(title = "自転車駐輪場の利用利用金収入額と駅の平均乗降客数") +
  xlab("駅の平均乗降客数(百人/日)") +
  ylab("自転車駐輪場の利用料金収入額(万円/月)") +
  geom_point() +
  geom_smooth(method = "lm", se=FALSE, color="black", formula = my.formula, size = 0.5)+
  stat_poly_eq(formula = my.formula, 
               aes(label = paste(..eq.label..)), 
               parse = TRUE) +
  theme_gray()

#問2 Table3の計算
table3 <-cbind(SIU,yy,xx,yy^2,xx^2,xx*yy)
table3

##問3 決定係数を求める
#yの予測値からの偏差平方和の平均(配布資料の2.2式)
Sxy2 <- (1/length(SIU$Income))*sum((SIU$Income - predict(result))^2)
Sxy2

#yの分散
Syy <- sum(yy^2)*(1/length(yy))
Syy

#決定係数
r2 <- 1-(Sxy2/Syy)

#相関係数
r <- sqrt(r2)

#Rのlm関数によって求めた決定係数との比較:summary関数を用いた表示
summary(result)

#Rのcor関数によって求めた相関係数との比較
cor(SIU$Income,SIU$UsersNum)

多変量データを扱う

      ◆データの読み込み

      多変量解析で用いるデータを,外部(パソコン上や,インターネット上)からRへ読み込む.今回の演習で扱うデータは,CSV(Comma-Separated Values)と呼ばれるデータ形式のものを利用する.CSVは,Excelやテキストエディタなどのソフトウェアで開くことが出来る.

      CSV形式のデータファイルは,read.csv関数で読み込むことが出来る.read.csvのあとの括弧()の中にある「file」や「header = TRUE」のことを引数(ひきすう)という.引数は複数指定することができ,左から「第一引数」「第二引数」という.第一引数は,読み込みたいファイルが置いてあるフォルダのパスとファイル名をつなげて指定する.

      read.csv(file, header = TRUE, sep = ",",...)

      ◆コロナウイルス感染者データの入手と読み込み

      都道府県別新型コロナウイルス感染者数マップ URL では,発表された症例一覧のCSVファイルが入手できる.

      コロナウイルス感染者データの読み込みと表示

      このCSVデータにはいくつかの欠損値などがあり扱いにくい.そこで,今回の演習用に,加工したデータを以下のURLに置いた.

      https://fnakai.web.nitech.ac.jp/data/COVID-19_modified.csv

      このデータをread.csv関数を使って読み込み,読み込んだファイルを「COVID-19」というオブジェクトに代入(付値)せよ.URL指定による方法でも,ローカルフォルダに保存してから読み込む方法でも,どちらでも良い.

      第一引数には,ファイルのパス/ファイル名を” “(ダブルクオーテーション)でくくって指定する.また,第二引数には,header= TRUEを指定する.これは「1行目は列名を意味しますよ」ということを示すものである.第3引数にはsep=”,”を指定する.sepという引数は,読み込むファイルが ,(カンマ)で区切られていることを示すものである.

      1.オンライン上のデータを読み込む方法(URLを指定してアクセス)

      ※今回の演習ではRstudio Cloudを使う都合上,こちらの方法で読み込む

      第一引数には,以下のURLを” “(ダブルクオーテーション)でくくって指定する.

      https://fnakai.web.nitech.ac.jp/data/COVID-19_modified.csv

      2.ローカルフォルダのデータを読み込む方法(フォルダのパスを指定してアクセス)

      データをダウンロードし,EIP2020に保存する.そして,そのデータをread.csv関数を使って読み込む.

      第一引数には,(1)フォルダのフルパス”C:/Users/Fuko Nakai/Desktop/EIP2020/NagoyaCity_population_en.csv “を指定する方法,(2)ファイル名”NagoyaCity_population_en.csv “だけ指定する方法がある.(2)は,CWDを省略した表記である.今回はCWDがEIP2020に指定されているため省略可能であるが,CWDとは異なるパスのファイルを読み込む場合には,フルパスを指定する.

      以下は,一度ローカルフォルダに保存してから読み込むケースである.colClassesという引数を用いて各列のデータ型を指定する.

      COVID19 <- read.csv("COVID-19_modified.csv",
                          sep=",",
                          colClasses = c("integer","integer","character","character","character","Date"))

      オブジェクト名を入力し,実行すると,読み込んだデータの中身を見ることができる.「COVID19」と入力し,中身を確認せよ.また,以下の表に示す列が現れることを確認せよ.

      COVID19
      データの列名内容
      ID本CSV内におけるデータの通し番号
      Age公表された年代。10歳刻み。 10歳未満の場合「0-10」と記載。実際の年齢が公表された場合にも年代に丸めて記載。不明もしくは非公表の場合には「不明」と記載。
      Hospital Pref受診都道府県
      Residential Pref居住都道府県(居住地)
      Gender公表された性別、男性、女性。 不明もしくは非公表の場合には「不明」と記載。
      Confirmation DatePCR検査における陽性が判明した日。 日付は日本時間(JST)。自治体の公表日(報道発表資料公開日)や、報道された日付ではない。
      演習用データ COVID-19_modified.csv の定義(引用:新型コロナウイルス感染者数マップ

      各列のデータの表示

      読み込んだデータの型がdata.frameという形式の場合,「オブジェクト名$列名」と指定することで,各列のデータのみを表示できる.今回は,既にdata.frame型になっている.たとえば,居住都道府県(居住地)のみのデータを表示したければ,以下のように入力すればよい.

      COVID19$Residential.Pref

      ◆データの要約

      膨大なデータの概観を得るためには,データの特徴を少数の値に要約する(まとめる)ことがもとめられる.ここでは,table関数,summary関数を用いたデータの要約をおこなう.

      問1 table関数を用いた都道府県別感染者数の集計

      COVID-19は,1つのレコードに感染者1名分のデータが入っている.これを,各列ごとに集計してみよう.まずは,下記のコードを入力してみてほしい.どのような結果が出てきただろうか?

      table(COVID19$Residential.Pref)
      ?table

      実行結果を踏まえて,以下の1,2に答えよ.

      1. Age,Hospital Pref,Residential Pref,Genderの4つの列について,table関数による集計を実行し,そのコードを示せ.
      2. 「?table」は,table関数がどのような関数を表示するコマンドである.これを参考に,table関数がどのような関数か,説明せよ.

      問2 summary関数を用いた要約

      下記のコードを実行せよ.

      summary(COVID19)

      列ごとに,「Min.」「1st Qu.」「Median」「Mean」「3rd Qu.」「Max.」「NA’s」という項目が表示される.これは,上から順に「最小値」「第 1 四分位点」「中央値」「平均」「第 3 四分位点」「最大値」「NAの数」を意味する.「NA」は,データの欠損を意味する.また,数値データ以外の列は,「Length」「Class」「Mode」となっており,それぞれ「データの数(行数),データ型,データ型」を意味する.

      summary関数の実行結果を踏まえて,以下の1,2に答えよ.

      1. 今回演習で扱うCOVID19データには何人分のデータが入っているか.
      2. Ageの列の平均値,最小値,最大値を求めよ.
      3. 今回Ageの列において,欠損しているデータはいくつあるか.

      ◆量的データの可視化

      膨大なデータの概観を把握するもう一つの手法は「可視化」である.量的データの可視化法として最も代表的なのがヒストグラム(度数分布)である.度数分布はhist関数を用いて表示することができる.

      問3 hist関数を用いた年代データの可視化

      年代に関する度数分布を表示する下記のコードを実行せよ.

      hist(x = COVID19$Age,
           xlab = "XXX",
           ylab = "XXX",
           main = "XXX",
           col = "red",
           border = "gray",
           breaks=seq(0,100,by=10))

      各引数の意味は以下の通りである.

      xヒストグラムを描く変数(ベクトル形式)
      breaksヒストグラムの横軸の範囲と分割の幅(ベクトル形式)
      xlab,横軸の名称(文字列)
      ylab縦軸の名称(文字列)
      mainヒストグラム上のタイトル(文字列)
      colヒストグラムの棒の色を指定(文字列または数値)
      border棒の枠の色を指定(文字列または数値)
      breaksベクトル形式で,階級分けの下端値から上端値の値を指定する.例えばbreaks=seq(0,100,by=10)は「0歳代から100歳代までの年齢を10歳刻みのヒストグラムに分けよ」という意味である.
      各引数の意味

      実行結果を踏まえて,以下の問いに答えよ.

      1. 縦軸に「頻度」,横軸に「年代」,タイトルに「年代のヒストグラム」と指定し,棒とその枠の色を「black」としたヒストグラムを描け.また,グラフは,形式を「PNG」にして,EIP2020フォルダに保存し,レポートに貼りつけること(図番号とキャプションもつけること).
      2. 一番感染者数が多い年代と,少ない年代を答えよ.また,描いたヒストグラムからわかることを説明せよ.

      問4 hist関数を用いた陽性判明日データの可視化

      陽性が判明した日に関する度数分布を表示する下記のコードを実行せよ.

      hist(x = COVID19$Confirmation.Date,
           breaks = length(unique(COVID19$Confirmation.Date)),
           xlab = "XXX",
           ylab = "XXX",
           main = "XXX",
           col = "gray",
           freq = TRUE)

      上記を実行した結果、以下のようなエラー文「’x’ must be numeric(オブジェクト’x’は実数型でなければいけない)」が出る場合がある。これは、COVID19$Confirmation.Dateというオブジェクトが、単なる文字列として扱われているためである。この場合、

      > hist(x = COVID19$Confirmation.Date,
      +      breaks = length(unique(COVID19$Confirmation.Date)),
      +      xlab = "XXX",
      +      ylab = "XXX",
      +      main = "XXX",
      +      col = "gray",
      +      freq = TRUE)
      Error in hist.default(x = COVID19$Confirmation.Date, breaks = length(unique(COVID19$Confirmation.Date)),  : 
        'x' must be numeric

      hist()関数を実行する「前」に以下のコードを実行する。as.Date()は、()内の日付に関するオブジェクトをcharacter型からDate型へ変換する関数である。変換した後の結果を、オブジェクトCOVID19$Confirmation.Dateに改めて代入する。

      COVID19$Confirmation.Date <- as.Date(COVID19$Confirmation.Date)

      hist関数の実行結果を踏まえて,以下の問いに答えよ.

      1. 縦軸,横軸,タイトルに適当(データを的確に表すよう)な文字列が入るよう,引数を指定したヒストグラムを描け.また,グラフは,形式を「PNG」にして,EIP2020フォルダに保存し,レポートに貼りつけること(図番号とキャプションもつけること).
      2. summary関数を用いて,いつからいつまでの期間のデータが収録されているかを示せ.
      3. 陽性が判明した日について,ヒストグラムからわかることを3つ以上挙げよ.

      ◆質的データの可視化

      質的データを可視化するには,各カテゴリに属する割合を図示するのが良い.ここでは円グラフを扱う.円グラフは,pie関数を用いて表示することができる.

      5 pie関数を用いた性別データの可視化

      性別に関する度数分布を表示する下記のコードを実行せよ.

      x <- table(COVID19$Gender)
      pie(x, clockwise = TRUE)

      第一引数には,各カテゴリの個体数をベクトルで指定する必要がある.第二引数のclockwiseには,カテゴリの順序を反時計回りに配置するかをTRUE,FALSEで指定する.

      実行結果を踏まえて,以下の問いに答えよ.

      1. グラフを描き,形式を「PNG」にして,EIP2020フォルダに保存し,レポートに貼りつけること(図番号とキャプションもつけること).
      2. 今回は「x <- table(COVID19$Gender)」を実行してから,「pie(x, clockwise = TRUE)」を実行している.この二行がどのような操作を意味するのか,なぜ一行目が必要であるのかを説明せよ.
      3. 円グラフからわかることを説明せよ.

      ◆データの抽出

      ここまでは,全国のデータを扱ってきたが,愛知県のデータだけを取り出して,そのデータの特性を見る.

      下記のコードを入力してみてほしい.急にややこしいのが出てきた,と思うかもしれないが,一つ一つ丁寧に見てみよう.

      AichiCOVID19 <- COVID19[which(COVID19$Residential.Pref=="Aichi"),]

      まず,以下のコードを実行してみてほしい.FALSEやTRUEという文字列が現れる.これは,COVID19$Residential.Prefの値が”Aichi”であればTRUE,そうでなければ”FALSE”を返している.

      COVID19$Residential.Pref=="Aichi"

      次に,以下のコードを実行してみる.which関数である.これは,which( )の中の論理式を満たす行の番号を抽出する関数である.つまりCOVID19$Residential.Prefの値が”Aichi”である行の番号一覧が返されていることになる.

      which(COVID19$Residential.Pref=="Aichi")

      最後に,以下のコードを実行してみる.以下のようにオブジェクト名[ ]と表記しているのは,[ ]の数字を使ってオブジェクトの何番目のデータを取り出すかを指定するものである.今回は行列データを扱っているのでオブジェクト名[i,j]でi行j列のデータを指定することが出来る.iもjも,ベクトルで指定することが出来る.which関数の結果はベクトル形式になっているから,そのベクトルの数値に該当する行のデータを返すことになる.

      COVID19[which(COVID19$Residential.Pref=="Aichi"),]

      問6 データの抽出

      全国のデータから岐阜県(”Gifu”)のデータだけを取り出し,オブジェクト名「GifuCOVID19」に付値せよ.また,そのコードを示せ.

      ◆発展課題(+10点)

      以下の問題は,できる範囲で取り組んでください.

      1. 好きな都道府県(愛知,岐阜,あるいはそれ以外)を選び,hist関数を用いた年代データと陽性判明日データ,pie関数を用いた性別データの可視化をおこない,保存し,レポートに張り付けよ.
      2. 結果について,全国を対象に分析した問1~問5の結果と比較し,考察しなさい.

      演習作業用フォルダの準備方法

      書いたプログラムや分析するデータを保存するフォルダを用意しておきます.演習の際には,このフォルダをワーキングディレクトリ(作業用フォルダ)として指定します.

      自分がどのフォルダで作業しているかを意識することは非常に大事です.適当なところに保存して「保存したプログラムがどこにあるかわからない,消えた」といったことにならないように,最後の確認までしっかりやりましょう.

      ◆演習作業用フォルダ(ワーキングディレクトリ:WD)の準備

      デスクトップ上で右クリック→「新規作成」→「フォルダー」から,新しいフォルダを作成し,「EIP2021」という名前にしておきます.

      EIP2021フォルダを右クリック→プロパティを選択すると,「場所:XXXXX」という項目が見られます.このパスの末尾に「\EIP2021」を足した文字列で示されるパスをWDに指定することにします.

      フォルダのプロパティ

      この場合のWDは以下の通りです.今後,演習で使うファイル類はすべてこれに入れてください.後でまとめて提出してもらいます.

      C:\Users\ユーザー名\Desktop\EIP2021

      ◆Rでワーキングディレクトリを指定する

      R上で,getwd()と入力して実行してみてください.以下のような値が返ってきます.getwd関数は,現在のワーキングディレクトリ(CWD: Current Working Directory)を返す関数です.

      > getwd()
      [1] "D:/documents"

      CWDを,先ほど作成した演習作業用フォルダ「C:\Users\ユーザー名\Desktop\EIP2021」に変更します.※ユーザー名は各自のフォルダのパスに依存しますので注意してください.フォルダの階層の区切りは「/」を使います.

      setwd("C:/Users/Fuko Nakai/Desktop/EIP2021")

      もう一度,getwd()と入力して実行してみてください.以下のような値が返ってきたら成功です.

      > getwd()
      [1] "C:/Users/Fuko Nakai/Desktop/EIP2021"

      ◆演習用エディタの立ち上げとスクリプトの保存

      「RConsole」と書かれたウィンドウ(コンソール画面)が現れていることを確認します.ここに直接コマンドを入力することもできますが,ここに打ち込んだ内容は,Rを終了すると消えてしまいます.そこで「Rエディタ」を立ち上げ,スクリプトファイルを新規作成し,保存することにします.

      Rstudioの場合

      左上に「Untitled」と書かれたタブ(Rエディタ)が出ていることを確認して,左上のタブの「File」→「Save as」をクリックします.

      先ほど作成したEIP2021内に「yyyymmdds_Name.R」という名前で保存します.「.R」というのはR拡張子です.ファイル名は何でも良いですが,後で誰が見ても内容のわかる内容にしましょう.yyyymmddには作成年月日を,Nameには自分の名前アルファベット表記で入れてください.

      保存したら,EIP2021の中に「yyyymmdds_Name.R」が出現していることを確認しましょう.演習のプログラムはこのファイル上に書き込み,上書き保存してください.

      図1 Rstudioの画面

      R Guiの場合

      メニューバーから「ファイル(File)」→「新しいスクリプト」を選択します.その後,下のような「無題 – Rエディタ」がでます.「ファイル」→「保存」で保存の操作ができます.

      Rの場合の表示画面

      以上で作業は終了です.

      for文を使いこなす

      for文を使えるようになると,いろいろ便利です.以下のような図も作れます.

      ◆準備

      setwd()でワーキングディレクトリを指定し,演習用フォルダを指定しておいてください.参考:地理空間情報の可視化

      ◆二項分布に親しむ

      表が出る確率がpのコインをn回投げて,表がk回出る確率の分布.

      ― 二項分布の数式 ―

      問1 パラメータがそれぞれ \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) において,表が出る回数を \(k\) と表す.このとき, \(k=20\)となる確率を求めよ.

      ヒント:dbinom(k,n,p)という関数を使うことで,\(B(n,p)\) において\(k\)が出る確率を求めることができる.

      dbinom(k,n,p)

      問2 パラメータがそれぞれ \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) から,20個の乱数をサンプリングせよ.

      ヒント:rbinom(size,n,p)という関数を使うことで,\(B(n,p)\) からsize個の乱数をサンプリングすることが出来る.

      rbinom(size,n,p)

      ◆for文を使ってみる!

      for文は,以下のような構文である.Rのfor文では,()内のiに,vectorの値をひとつずつ入れて, {} 内の処理をおこなう.たとえば,for(i in 1:5)であれば,i=1, i=2, i=3, i=4, i=5をそれぞれ代入し,{}内のprint(i)を実行する.print関数は()内のオブジェクトをコンソールに吐き出す関数である.

      printをしないでiだけ書くとどうなるかも試してみよう.

      for (i in vector) {
        print(i)
      }

      問3 \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) において、表が出る回数\( k \)が, \( 0,1,2,…50 \) となる確率をすべて計算せよ.

      ヒント:もちろん,1行ずつkを変えて…となると大変.for文を使おう.????に繰り返したい値をベクトルに入れて,指定する.i,n,pもそれぞれ指定する.print関数をつけないとどうなるか…?

      for (i in ????) {
        dbinom(i,n,p)
      }

      問4 \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) から、20個の乱数をサンプリングする,という操作を100回繰り返し,その結果を表示せよ.

      ヒント: ????に繰り返したい値をベクトルに入れて,指定する.i,n,pもそれぞれ指定する.print関数を使って表示する.

      for (j in ????) {
        rbinom(size,n,p)
      }

      ◆for文を使って可視化する

      for文を使うと,条件を少しずつ変えたグラフなども簡単に作れる.

      問5 \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) において、表が出る回数\( k \)が, \( 0,1,2,…50 \) となる確率をすべて計算し,x軸にkを,y軸にkが出る確率をとった二次元のグラフを作成してみよう.

      ヒント1:これもfor文を使うこと(for文を使わない方法もある).

      ヒント2:グラフを出力する関数はplot()である.plot(x,y)で,横軸がx,縦軸がyのグラフが描かれる(xとyのベクトルの長さは同じでなければならない).

      ヒント3:par(new=T)をplot関数の前に指定することで,その前に書いたグラフに重ね書きができる.

      for (i in ????) {
        plot(i,dbinom(i,n,p))
        par(new=T)
      }

      ヒント4:x軸とy軸がぐちゃぐちゃになったのではないでしょうか?そういう時は,以下のようにxlim,ylim というパラメータを指定することで,毎回同じ範囲の軸を描くことが出来る.1回目だけ描いて2回目以降は描かないように指定することで,重ね書きによって文字が分厚くなることも防げそうだが,今回はそれはやらない.

      xlim = c(0,50),ylim = c(0,0.2)

      問6  \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) から、20個の乱数をサンプリングする,という操作を100回繰り返し,その結果をヒストグラムに書き表してみよう.

      ヒント:breaksというパラメータを使って,ヒストグラムの範囲と幅を指定することが出来る.たとえば,以下のようにパラメータ指定すると,0から50の値を幅1で表示する,というものになる.

      breaks=seq(0,50,1)

      ヒント2:黒々として見にくければ,colというパラメータで色を分けて指定することもできる.col = i のように指定すれば,毎回色を変えて可視化することができる.

      問7  \(n=50, p=0.3\) の 二項分布\(B(50,0.3)\) において、表が出る回数\( k \)が, \( 0,1,2,…50 \) となる確率を計算し,その確率に各々50をかけた値をy軸にして表示せよ.また,これを問6のグラフに重ね合わせてみよう.

      ◆ファイルの出力

      問8 ファイルに出力する.

      まずは,setwdで保存したいフォルダのパスを指定する.

      setwd("保存したいフォルダのパス")
      getwd()

      ファイルに画像データを保存する場合は, plot()の前 にpng(“パス/ファイル名”)を実行し, plot()の実行後,dev.off()を実行することで,plot()で描いたグラフが “パス/ファイル名” に保存される.

      ファイル名が同じだと,毎回上書きされてしまう.これでは困る.ファイル名を各繰り返しの度に変えたい.

      そこで,paste()という関数を使う.これは,paste(“Hides”,”hima”)のように実行すると”Hideshima”のように,文字列をくっつけてくれる関数である.これを使って,毎回異なるファイル名を指定できるようにしてみよう.

      sep = “” というパラメータをつけないと, “Hides hima” のようにスペースが入る.

      paste("Hides","hima",sep = "")

      実行後,指定したフォルダ内を確認してみよう.

      for (i in 0:50) {
        png(paste("binom",i,".png"))
        hist(rbinom(20,50,0.3),xlim = c(0,50),ylim = c(0,20),breaks=seq(0,50,1),col = i)
        dev.off()
      }

      ◆動画の作成

      「 png 複数 gif化 」等で各自ネットで調べてください.

      ◆演習の解答

      以下は解答例です.もっといいやり方もあると思うので,各自模索してみてください.

      下記コードのダウンロードはこちらから.

      # 2020.6.3
      # coded by F.Nakai
      
      #二項分布
      ### 肩慣らし
      #Q1: p=0.3, N=50の二項分布において、k=20となる確率
      dbinom(20,50,0.3)
      
      #Q2: p=0.3, N=50の二項分布から、20個の乱数をサンプリングする
      rbinom(20,50,0.3)
      
      ### for文を使ってみる!
      #Q3: p=0.3, N=50の二項分布において、K=0,1,2,...50となる確率を計算する
      
      for (i in 0:50) {
        print(dbinom(i,50,0.3))
      }
      
      #Q4:p=0.3, N=5の二項分布から、20個の乱数をサンプリングするのを100回繰り返す
      
      for (j in 1:100) {
        print(rbinom(20,50,0.3))
      }
      
      ### for文を使って可視化してみる
      #Q5: p=0.3, N=50の二項分布において、K=0,1,2,...50となる確率を計算して可視化する
      for (i in 0:50) {
        print(dbinom(i,50,0.3))
        plot(i,dbinom(i,50,0.3),xlim = c(0,50),ylim = c(0,0.2))
        par(new=T)
      }
      
      
      #Q6:p=0.3, N=50の二項分布から、20個の乱数をサンプリングするのを100回繰り返す
      
      par(new=F)
      for (j in 1:100) {
        print(rbinom(20,50,0.3))
        hist(rbinom(20,50,0.3),xlim = c(0,50),ylim = c(0,20),breaks=seq(0,50,1),col = j)
        par(new=T)
      }
      
      #Q7: p=0.3, N=50の二項分布において、K=0,1,2,...50となる確率を計算し、回数に変換して可視化する
      
      par(new=T)
      for (i in 0:50) {
        print(dbinom(i,50,0.3))
        plot(i,dbinom(i,50,0.3)*50,xlim = c(0,50),ylim = c(0,20))
        par(new=T)
      }
      
      #Q8: ファイルにつくったグラフを保存する.
      
      #出力するフォルダを指定する.
      setwd("保存したいフォルダのパスを設定")
      getwd()
      
      paste("hides","hima",sep = "")
      
      #for文で1つずつグラフを書いていく
      par(new=T)
      for (i in 0:100) {
        png(paste("binom",i,".png"))
        hist(rbinom(i*10,50,0.3),xlim = c(0,50),ylim = c(0,300),breaks=seq(0,50,1),col = "gray")
        dev.off()
      }
      
      #maptoolsライブラリを使ってみる
      #グラフのプロットにラベルを付ける
      library(maptools)
      mes <- c("今","日","は","お","つ","か","れ","さ","ま","で","し","た","!")
      mes1 <- length(rep(mes,5))
      
      for (i in seq(1,50,1)) {
        png(paste("binom",i,".png"))
        plot(i,dbinom(i,50,0.3),xlim = c(0,50),ylim = c(0,0.2),col = "white",pch = 19,cex = 10)
        pointLabel(x=i, y=dbinom(i,50,0.3), labels=mes[i])
        dev.off()
      }