Pocket

Rを使わない人にはなんのこっちゃという話で恐縮だが、院生と、

に格闘する日々。個人的には練習問題の答えが載っていないのがいい。馴染みのない事象が例となることが多いのがツラいとはいえ、その章の内容との対応でよく考えて配置されており、かなり頭をひねることになる。ググっても解決しないところで、久々に感じるソリッド感にヒリヒリする。

4章の練習問題の1(賭博市場に基づく予測)はひときわ難しく、3問目、4問目辺りで数日呻いた。

4問目では、2008年の全米の世論調査の予測について、選挙までの直近90日について民主党候補者の選挙人票数の予測値を図示することが求められる。データはこちら

  1. 2008 Presidential Election Data: pres08.csv
  2. 2008 Presidential Polling Data: polls08.csv

の2つを用いる。

なお、世論調査は各州で毎日行われているわけではない。したがってある州において、選挙運動期間の直近90日間の各日について、その日に最も近いときに行われた世論調査から平均の勝利マージンを計算する。もし、同じ日に複数の世論調査が行われていた場合は、それらの世論調査を平均する。各州の最新の予測に基づいて、オバマが獲得すると予測された選挙人票を合計しよう(p. 247)。

というのをやってみると、

pres08 <- read.csv(“pres08.csv”)
polls08 <- read.csv(“polls08.csv”)
polls08.pres <- merge(polls08, pres08, by = “state”) #polls08をpres08とマージする

polls08.pres$middate <- as.Date(polls08.pres$middate) #polls08の日付処理
polls08.pres$DaysToElection <- as.Date(“2008-11-04”) – polls08.pres$middate #選挙までの日数を出しておく
polls08.pres$DaysToElection <- as.numeric(polls08.pres$DaysToElection) #後の計算で不具合出たので数値データに戻す
polls08.pres$polls.margin <- polls08.pres$Obama.x – polls08.pres$McCain.x #polls08のマージンを計算しておく
state.polls <- state.EV <- rep(NA, 51) #51州のデータ格納場所
st.names <- unique(polls08.pres$state) #州の名前取り出し
names(state.polls) <- as.character(st.names) #州の名前割り当て
day.polls.ev <- rep(NA, 90) #90日間のデータ格納場所
for (i in 1:90){

for (j in 1:51){
state.data <- subset(polls08.pres, subset = (state == st.names[j])) #州ごとの部分集合化
state.data$day.diff <- (state.data$DaysToElection – i)^2 #各州の調査データの選挙日までの日数から1〜90日間を引いて(プラスマイナスあるので)二乗する
latest <- subset(state.data, subset = (state.data$day.diff == min(state.data$day.diff))) #上の値が最も小さい=近い日付のデータで部分集合化
state.polls[j] <- mean(latest$polls.margin) #同日に複数調査があった時のために平均を取っておく
state.EV[j] <- mean(latest$EV) #同日に複数調査があった時のために平均を取っておく
}

state.data2 <- cbind(state.polls, state.EV) #無駄かもしれないが下の計算のために対応させておく
day.polls.ev[i] <- sum(state.EV[state.polls > 0]) #マージンがプラスの州のみ選挙人票を合計
}

plot(90:1, day.polls.ev, type = “b”, xlim = c(90, 0), ylim = c(200, 400), col = “blue”, xlab = “選挙までの日数”, ylab = “選挙人票予測値”)
points(0, 365, pch = 19, col = “blue”)
abline(v = 0)

というコードに至って何とか出すことができたように思うのだが、仮にこれでOKだったとしても、もっとうまいやり方があるように思う(ただし、which.max()、which.min()といった関数はこの章には登場していないし、パッケージもまだ一切紹介されていない)。どうだろうか。

追記(18/06/04):

入れ子のfor()の中の、

  • state.data$day.diff <- (state.data$DaysToElection – i)^2

  • state.data$day.diff <- (state.data$DaysToElection – (91 – i))^2

にする必要があることに気づきました。選挙90日前から1日前までの方向でプロットしている=day.polls.ev[i]に格納されたデータを90番目から降順で並べているということなので、最初の式だとiの1番目に90日前のデータが、iの90番目に1日前のデータが入ってしまい、結果が逆になってしまうため。選挙が近づくにつれて予測が実測(オバマさんは実際には365人票獲得した)から離れていくのは不自然ですもんね。