カテゴリカルデータ解析読書メモ(第3章)

第3章の内容は大体知ってる事なのでささっと。

二項検定

> binom.test(405, 765)

	Exact binomial test

data:  405 and 765
number of successes = 405, number of trials = 765, p-value =
0.1116
alternative hypothesis: true probability of success is not equal to 0.5
95 percent confidence interval:
 0.4933327 0.5652633
sample estimates:
probability of success 
             0.5294118 

pのデフォルトは0.5なのでテキストの例では省略できる。
ついでに95%信頼区間が分かる。

多項分布

多項分布用に*multinom()関数シリーズが用意されている。

> p <- c(0.382, 0.219, 0.305, 0.094)
> x <- c(39, 16, 27, 15)
> dmultinom(x, prob = p)
[1] 0.0001047239

カイ二乗検定

> x <- c(62, 52, 53, 38, 46, 49)
> chisq.test(x)

	Chi-squared test for given probabilities

data:  x
X-squared = 6.36, df = 5, p-value = 0.2727

chisq.test()のpの初期値は等確率なのでこちらもテキストの例だと省略出来る。

カテゴリカルデータ解析読書メモ(第2章)

気付いたら買って本棚に飾ってあったので読んでいる。

カテゴリカルデータ解析 (Rで学ぶデータサイエンス 1)

カテゴリカルデータ解析 (Rで学ぶデータサイエンス 1)

準備

install.packages("vcd")
library(vcd)
data("Arthritis")

Arthritisは腱鞘炎に関する臨床試験のデータで、処置と経過、性別と年齢のデータが個票として入っている。

個票形式のデータの集計とプロット

xtabs()は表形式の集計を行う。集計の仕方を式の形で与えることができる。

> xtabs(~ Improved, data = Arthritis)
Improved
  None   Some Marked 
    42     14     28 

このままbarplot()に与えれば棒グラフが作成できる。

IMP2 <- IMP[order(IMP, decreasing = TRUE)]
barplot(IMP2)

f:id:Rion778:20160725003837p:plain
クロス集計をしたい場合は、条件を+で繋ぐ。

> xtabs(~ Treatment + Improved, data = Arthritis)
         Improved
Treatment None Some Marked
  Placebo   29    7      7
  Treated   13    7     21

3変数以上は配列になる。

> xtabs(~ Treatment + Improved + Sex, data = Arthritis)
, , Sex = Female

         Improved
Treatment None Some Marked
  Placebo   19    7      6
  Treated    6    5     16

, , Sex = Male

         Improved
Treatment None Some Marked
  Placebo   10    0      1
  Treated    7    2      5

I()を用いると、特定の変数の組み合わせをまとめて行や列に指定できる。表形式に抑えたい場合に便利だ。

> xtabs(~ I(Sex:Treatment) + Improved, data = Arthritis)
                Improved
I(Sex:Treatment) None Some Marked
  Female:Placebo   19    7      6
  Female:Treated    6    5     16
  Male:Placebo     10    0      1
  Male:Treated      7    2      5

集計結果を比率で表示したい場合はprop.table()を用いる。margin=引数によって行和または列和を1にするように制御できる。

> prop.table(Ctable, margin = 1) # margin 1:行和を1 2:列和を1
         Improved
Treatment      None      Some    Marked
  Placebo 0.6744186 0.1627907 0.1627907
  Treated 0.3170732 0.1707317 0.5121951

prop.table()で比率に変換した表をbarplot()に渡すことで、帯グラフが作成できる。

> Ctable.p <- prop.table(Ctable, margin = 1)
> barplot(t(Ctable.p), horiz = T, axes = F,
+ xlab = "Improved(None Some Marked)")
> axis(1, seq(0, 1, by = 0.2), paste(seq(0, 100, by = 20), "%"))

f:id:Rion778:20160725004739p:plain
多変数間のクロス集計結果を図示するにはモザイクプロットが便利である。

> Ctable3 <- xtabs(~ Treatment +  Sex + Improved, data = Arthritis)
> mosaicplot(Ctable3, col = TRUE)

f:id:Rion778:20160725005102p:plain
なお、個票形式のデータであればxtabsにより集計する必要はなく、直接mosaicplot()に渡せばよい。

mosaicplot(~ Treatment + Sex + Improved, data = Arthritis,
           col = TRUE)

集計データの扱い

集計データとは、変数の組み合わせとその度数をまとめた形式のデータである。

> data("DanishWelfare")
> head(DanishWelfare)
  Freq Alcohol Income  Status         Urban
1    1      <1   0-50   Widow    Copenhagen
2    4      <1   0-50   Widow SubCopenhagen
3    1      <1   0-50   Widow     LargeCity
4    8      <1   0-50   Widow          City
5    6      <1   0-50   Widow       Country
6   14      <1   0-50 Married    Copenhagen

集計データをxtabs()により集計する際には、式の左辺に度数を指定する必要がある。

> xtabs(Freq ~ Alcohol, data = DanishWelfare)
Alcohol
  <1  1-2   >2 
2339 2083  722 

モザイクプロットを作成したい場合、xtabs()による集計を省略することはできないので注意する。

Ctable4 <- xtabs(Freq ~ Status + Alcohol, data = DanishWelfare)
mosaicplot(Ctable4, col = TRUE)

f:id:Rion778:20160725005654p:plain

表形式→集計形式→個票

既に表形式になってしまっているデータを集計形式に戻すのは簡単で、単にdata.frame()に渡せばよい。

> dtable <- matrix(c(2, 18, 3, 17, 9, 11, 15, 5, 18, 2), nr = 2)
> dimnames(dtable) <- list(effect = list("あり", "なし"),
+                          dose = list("1", "2", "3", "4", "5"))
> class(dtable) <- "table"
> dose_effect <- data.frame(dtable)
> head(dose_effect)
  effect dose Freq
1   あり    1    2
2   なし    1   18
3   あり    2    3
4   なし    2   17
5   あり    3    9
6   なし    3   11

集計形式から個票形式に戻すにはapply()などを駆使する。

> DW <- data.frame(lapply(DanishWelfare,
+ function(i) rep(i, DanishWelfare[,"Freq"])))
> DW2 <- DW[-1]
> head(DW2)
  Alcohol Income Status         Urban
1      <1   0-50  Widow    Copenhagen
2      <1   0-50  Widow SubCopenhagen
3      <1   0-50  Widow SubCopenhagen
4      <1   0-50  Widow SubCopenhagen
5      <1   0-50  Widow SubCopenhagen
6      <1   0-50  Widow     LargeCity

カテゴリーの編集

カテゴリー変数を編集したい場合は、直接書き換えてしまうことができる。

> levels(DanishWelfare$Income)
[1] "0-50"    "50-100"  "100-150" ">150"   
> levels(DanishWelfare$Income) <- c("0-100", "0-100",
+ "100<", "100<")
> xtabs(Freq ~ Income, data = DanishWelfare)
Income
0-100  100< 
 2042  3102 

量的変数を大きさで区切ってカテゴリー変数にしたい場合は、cut()が便利だ。

> Arthritis$CatAge <- cut(Arthritis$Age, 
+                         breaks = 2:8 * 10,
+                         labels = 2:7 * 10,
+                         right = TRUE)
> head(Arthritis)
  ID Treatment  Sex Age Improved CatAge
1 57   Treated Male  27     Some     20
2 46   Treated Male  29     None     20
3 77   Treated Male  30     None     20
4 17   Treated Male  32   Marked     30
5 36   Treated Male  46   Marked     40
6 23   Treated Male  58   Marked     50

Rで複数条件抽出&集計

f:id:Rion778:20160714214916p:plain
このようなデータフレームがあって、条件c1とc2に基づいて何らかの集計をしたいとする。
また、データフレームはdfというオブジェクトに代入されているとする。

tapply

> with(df, tapply(v, list(c1, c2), mean))
         1        2
a 1.689910 2.563432
b 1.780409 2.568772

by

> with(df, by(v, list(c1, c2), mean))
: a
: 1
[1] 1.68991
----------------------------------------------------------------------------- 
: b
: 1
[1] 1.780409
----------------------------------------------------------------------------- 
: a
: 2
[1] 2.563432
----------------------------------------------------------------------------- 
: b
: 2
[1] 2.568772

aggregate

> with(df, aggregate(v, list(c1, c2), mean))
  Group.1 Group.2        x
1       a       1 1.689910
2       b       1 1.780409
3       a       2 2.563432
4       b       2 2.568772

dplyr(group_by, summarize)

> library(dplyr)
> df %>% group_by(c1, c2) %>% summarize(mean(v))
Source: local data frame [4 x 3]
Groups: c1 [?]

      c1    c2  mean(v)
  <fctr> <int>    <dbl>
1      a     1 1.689910
2      a     2 2.563432
3      b     1 1.780409
4      b     2 2.568772

まとめ

Rでやるべき。

Excelで複数条件抽出&集計

f:id:Rion778:20160713213905p:plain
このようなデータがあって、条件1と条件2に基づいて何らかの集計をしたいとする。

AVERAGEIFS

平均値を計算したいのであれば、AVERAGEIFS関数があるので、例えばこのように入力する。

=AVERAGEIFS(平均対象範囲,条件範囲1,条件1,条件範囲2,条件2)

最初の例で言えば、条件がこのように入力されているとして、
f:id:Rion778:20160713215530p:plain
入力は次のようになる。

=AVERAGEIFS(C:C,A:A,F3,B:B,G3)

AVERAGEIFSは高速に動作するので、列全体を範囲指定してもあまり問題が無い。
同様の集計関数にはCOUNTIFS、SUMIFSなどがあり、いずれも高速である。なお、Excel2007以降で使える。

配列数式

平均、カウント、合計以外の集計をしたい場合、悪名高き配列数式を使うという手段がある。
配列数式は配列を渡して配列が返ってくる仕組みで、一人で使っている分には便利だが、他人にファイルを引き継ごうとすると配列数式の説明を漏れなく行う必要があり、大変面倒くさいという代物である。
AVERAGEやVAR.Sなどのセル範囲を引数として受け取る関数は、セル範囲の代わりに配列を渡しても良いので、IFを組み合わせて配列を作成し、それを渡せば良い。

=AVERAGE(IF(IF(A1:A10000=F3,TRUE,FALSE)*
            IF(B1:B10000=G3,TRUE,FALSE),
            C1:C10000,""))

IF文中のTRUE、FALSEは1、0でも良い。
この式をCtrl+Shiftを押下しながら確定すると、配列数式に変換されて式の両端に{}が付く。見た目には{}以外の変化が無いので、大変分かりにくい。
そして配列数式の最大の欠点として、「遅い」というものがある。上記例ではわざわざセル範囲を1万行に制限してあるが、これをしないと1秒くらいの計算時間がかかってしまう。配列数式を使う場合、範囲指定は狭ければ狭いほど良い。

名前付き範囲

この配列数式の欠点を補う方法として、名前付き範囲を使用するという方法がある。
Excelにおける名前とは変数名のようなもので、指定のセル範囲を指定の名前で表記できるというものである。例えば、前述の式を次のように記述できる。

=AVERAGE(IF(IF(条件1=F3,1,0)*
            IF(条件2=G3,1,0),
            値,""))

これで大分可読性が向上する。
名前はリボンの[数式]から[名前の定義]で定義する。
ここで、次のように入力する。
f:id:Rion778:20160713222641p:plain
このようにOFFSET関数で参照範囲を定義することで、参照範囲が入力状況に対応して自動的に伸縮し、必要最低限の参照範囲となり、計算時間を節約できる。
なお、COUNTAで参照する列は、定義から想像出来ると思うが、全ての行に値が入っているような列でなければならない。MATCH関数等と組み合わせることで空白を許容することも可能であるが、長くなるのでここでは説明しない*1
なお、名前には拡大倍率を40%以下にするとどこに名前を設定しているか一目で確認できるという便利機能があるが、上記の方法で設定した名前にはこの手段が使えない。
f:id:Rion778:20160713223803p:plain

まとめ

Rでやるべき。

*1:詳しい方法についてはExcel Hacks 第2版― プロが教える究極のテクニック140選に記述があるが、多分適当にググっても出てくるだろう。

グループ変数に応じて複数の折れ線グラフを書く

緑色の本のp.119に載っている図と似たものを書こうとして、

d <- data.frame(q = rep(c("q0.1", "q0.3", "q0.8"), c(9, 9, 9)),
                p = c(dbinom(0:8, 8, 0.1), dbinom(0:8, 8, 0.3), dbinom(0:8, 8, 0.8)),
                y = rep(0:8, 3))

というようなデータを準備したものの、baseパッケージではどうプロットしたら良いものか若干悩んだ。

baseの例

# base
matplot(reshape(d, timevar = "q", idvar = "y", direction = "wide")[, -1], 
        ylab = "p", xlab = "y", xaxt = "n", type = "b", pch = 16, lty = 1)
axis(1, at = 1:9, labels = 0:8)
legend("topright", inset = 0.05,
       legend = c("q = 0.1", "q = 0.3", "q = 0.8"),
       col = 1:3,
       pch = 1,
       box.lty = 0)

f:id:Rion778:20160705221323j:plain
linesで重ねる方法もあるけどいずれにせよ面倒だし使い回ししにくい。もっと良い方法はないものか。

続いてlatticeで描いてみた。

# lattice
library(lattice)
xyplot(p ~ y, data = d, group = q, type = "b", 
       auto.key = list(text =c("q = 0.1", "q = 0.3", "q = 0.8")))

f:id:Rion778:20160705221128j:plain
凡例の編集をしようと思わなければ書式が素直で一番理解しやすい様に思う。

ggplot2

# ggplot2
# install.packages("ggplot2")
library(ggplot2)
ggplot(data = d, aes(x = y, y = p, col = q)) + geom_point() + geom_line() +
  scale_color_hue(label = c(q0.1 = "q = 0.1", q0.3 = "q = 0.3", q0.8 = "q = 0.8"))

f:id:Rion778:20160705221214j:plain
latticeとさほど手間は変わらないけど、ggplot2はどうも覚えにくい気がする。初心者にaes()とかどう教えたら良いのかと毎回悩む。

RStudioのキーバインド変更

Windowsでのお話。

Tools -> Modify Keyboard Shortcuts...

で出来るようになっているという話だけど、Ctrl+hをBackSpaceにしたいとかCtrl+zをPgUpにしたいとか思ってもどうもうまく出来ないので結局AutoHotkeyを使うことにした。ほんの少しゴニョゴニョしたいだけならAutoHotkeyが一番手軽な気がする。

  1. AutoHotkeyを入手&インストール(AutoHotkey)
  2. 拡張子.ahkなファイルに下記のスクリプトを記述して保存後ダブルクリック
#IfWinActive ahk_class Qt5QWindowIcon
^h::Send {BS}
^z::Send {PgUp}
#IfWinActive

ahk_classはAutoHotkeyに同梱のActive Window Info (Window Spy) で調べる。

ggplot2で凡例のラベルと項目名を操作する

ラベルと項目名を操作する

以下の説明ではggplot2を含めて3つのパッケージを使う。

library(dplyr)
library(tidyr)
library(ggplot2)

データは次のように準備した。

# テストデータの準備
testdata <- data.frame(x = seq(1, 10, 0.1)) %>%
  mutate(sin = sin(x), cos = cos(x))

散布図形式のプロットに適した形にデータフレームを整形する。

# 散布図の骨格を決める
p <- testdata %>%
  gather(ftype, val, -x) %>% # x以外の変数をvalにまとめ、列名をftypeにグループ変数として格納する
  ggplot(aes(x = x, y = val))

geom_line()を使ってグラフを描く。このとき、colorやltyなどの審美的属性にグループ変数をマッピングすることで変数をグループ別にプロットできる。そして、凡例は勝手に追加される*1

# colorをftypeにマッピングする
p + geom_line(aes(color = ftype))

f:id:Rion778:20160111202035p:plain
凡例のラベルを操作する簡単な方法はlabs()関数を使うこと*2で、例えば

p + geom_line(aes(color = ftype)) + labs(color = "関数")

のようにしてやればよい。
しかし、項目名(ここでのsinとcos)まで変更しようとすると、labs関数では設定ができない。項目名を設定するには、スケールを調整する関数を使用する必要がある。カラースケールの場合はscale_color_◯◯()関数にlabels引数を設定する。◯◯の部分にはhueやgreyなどスケール名が入るが、デフォルトの配色ではhueである。

# colorをftypeにマッピングし、凡例のラベルを変更する
p + geom_line(aes(color = ftype)) +
  scale_color_hue(name = "関数", labels = c(sin = "正弦", cos ="余弦") ) +
  theme_grey(base_family = "HiraKakuProN-W3") # OS Xで日本語をプロットする際にはbase_familyの指定が必要

f:id:Rion778:20160111212059p:plain

複数の審美的属性が1つのグループ変数に割り当てられている場合

1つのグループ変数に複数の審美的属性を同時にマッピングすることもできる。

# colorとltyの2属性にftypeをマッピングしたプロットを作成
p2 <- p + geom_line(aes(color = ftype, lty = ftype))
# そのままプロット
p2

f:id:Rion778:20160111212403p:plain
このとき、ラベルの片方だけを変更してしまうと、凡例が2つに分裂してしまうので注意が必要である。

theme_set(theme_grey(base_family = "HiraKakuProN-W3")) # themeのデフォルト設定そのものを変更
# 凡例のラベルをcolorの方だけいじった場合
p2 + scale_color_hue(name = "関数", labels = c(sin = "正弦", cos ="余弦"))

f:id:Rion778:20160111212522p:plain
これを防ぐには、2つの凡例に全く同じラベル名と項目名を設定する。なお、線種のスケールはscale_linetype()で調整できる。

# 凡例のラベルを両方いじった場合
p2 + scale_color_hue(name = "関数", labels = c(sin = "正弦", cos = "余弦")) +
  scale_linetype(name = "関数", labels = c(sin = "正弦", cos = "余弦"))

f:id:Rion778:20160111213151p:plain
labs()を使ってラベルだけを変更する場合も同様で、

p2 + labs(color = "関数", lty = "関数")

のようにしてやる必要がある。

*1:baseパッケージでは凡例は基本的にはlegend()関数などで明示的に追記する必要がある。

*2:labs()関数は他にもtitleやx軸/y軸ラベルの設定もできる。

facetのstripのtextを変更する

ggplot2でfacet_gridやfacet_wrapを使ってグラフを分割描画した際に、各グラフについているラベル(strip)のテキストは、何もしなければ分割に用いたグループ名が自動的に入る。
例:

ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) +
  geom_point() + facet_grid(.~Species)

f:id:Rion778:20160103192059p:plain
このラベル部分はlabeller functionという関数で制御されていて、標準でいくつかの関数が用意されている(help(labellers)を参照のこと)。
これをマニュアルで設定するためには、これまではlabeller functionを自分で書く必要があった(cf. r - ggplot: How to change facet labels? - Stack Overflow)。定義したlabeller functionをfacet_gridの引数labellerに与えることで目的が達成される。
例:

# これまでのlabeller functionの作り方
labeli <- function(variable, value){
  names_li <- list("setosa" = "せとさ",
                   "versicolor" = "ばーじからー",
                   "virginica" = "ばーじにか")
  return(names_li[value])
}

theme_set(theme_gray(base_family="HiraKakuProN-W3"))
ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) + 
  geom_point() +
  facet_grid(.~Species, labeller = labeli)

f:id:Rion778:20160103192434p:plain
ggplot2のバージョンアップにともなって、labeller functionをもう少し分かりやすく書ける関数、as_labellerが追加された。

labeli <- as_labeller(c(`setosa` = "せとさ",
                         `versicolor` = "ばーじからー",
                         `virginica` = "ばーじにか"))

出来上がったlabeller functionの使い方に変更は無い。

飽和水蒸気圧の求め方

何年か前に飽和水蒸気圧の求め方に関して、Goff-Gratchの式やTetensの式やMurrayの式について少し触れたことがあった*1のだが、最近Wikipediaを見ていたらTetensの式だと思っていたものが

Tetens(1930)のパラメータ値によるAugust他の式

飽和水蒸気量 - Wikipedia

という表記になっていた。この部分はTetensの式となっていたものが割と最近更新された様子である。

Tetensの式はTetensの式ではない

Tetensの式やMurrayの式と呼ばれているこれらの式は、Magnusの式(後述するがこの呼称も適切ではない)と呼ばれている次式、
e_s=C \exp \left( \frac{A t}{B + t} \right)
のパラメータA, B, Cを定めたものに相当し、基本的には同様の式である。Tetensのパラメータがそうであるように、自然対数部分を常用対数として使うパラメータもある。
Tetens(1930)*2によるパラメータを用いたものがTetensの式、Murray(1966)*3のパラメータを用いたものがMurrayの式として呼ばれていたものに該当する。Tetensのパラメータが特に有名となっているのは、少ない桁数でそこそこ正確な近似を与えたという点で優れていたから、ということの様である。

August-Roche-Magnusの式

英語版Wikipediaのクラウジウス-クラペイロンの関係式のページを見ると、飽和水蒸気圧の求め方が応用例としてあげられており、次のような記述がされている。

Fortunately, the August-Roche-Magnus formula provides a very good approximation, using pressure in hPa and temperature in Celsius:

e_s(T)= 6.1094 \exp \left( \frac{17.625T}{T+243.04} \right) [7][8]

(This is also sometimes called the Magnus or Magnus-Tetens approximation, though this attribution is historically inaccurate.[9])

Clausius–Clapeyron relation - Wikipedia, the free encyclopedia

出典としてあげられているLawrence(2005)*4にもあるように、この式についての初期の仕事はAugust(1828)によってなされており、August-Rocheの式またはAugust-Roche-Magnusの式と呼ぶのがふさわしいようだ。このあたりに基づいて日本語版Wikipediaの記述も変更されたのだろう。

非August-Roche-Magnus式

August-Roche-Magnusの式の形をしていない飽和水蒸気圧を求める式として、Goff-Gratch(1946)の式や、Wexler(1976)の式、Sonntag(1990)の式などがあり、これらはより正確な飽和水蒸気圧を与えるとされている。
計算そのものはコンピュータを用いればすぐに終わるものだが、いずれも式が長く係数の桁数が多いので、そこそこの精度があれば良いという用途には不便である。

結局どうやって求めるの

英語版のクラウジウス-クラペイロンの関係式のページから引用した式の係数は、日本語の教科書によく載っている値や、日本語版Wikipediaに載っている値と若干違う。
この値は、Alduchov and Eskridge(1996)*5によりあたえられたもので、上に述べた3つの非Augst-Roche-Magnus式との相対誤差が、いずれに対しても0.4%以下となる(水上で-40℃〜50℃、氷上で-80℃〜0℃(氷上のものは係数が異なる)の範囲)ように選んだものである。有効な温度範囲も明示されているので、基本的にはこの式を使っておけば良いだろう。
Rの関数として定義する場合の例を示す。

AE1995 <- function(t, s.cool=FALSE){ # 入力:℃ 出力:hPa
  ifelse(t > 0 | s.cool,
         6.1094 * exp(17.625 * t / (243.04 + t)), # 水上or過冷却水(s.cool=TRUE)
         6.1121 * exp(22.587 * t / (273.86 + t))  # 氷上
  )
}

Goff-Gratchの式との比較

Goff-Gratchの式をコントロールとして、AE1995を含むいくつかの式の相対誤差をプロットすると、以下のようになる。
f:id:Rion778:20160103135736p:plain
日常的な気温の範囲ではどれも大差なく、むしろAE1995は氷点以上のあてはまりがやや悪いようにも見えるが、AE1995はWexler(1976)やSonntag(1990)といった新しい式も含めた評価をしている点を注意しておく必要がある。面倒なので今回はやらないが、これらの式との比較をしてみるのも面白いだろう。
Okadaの式の当てはまりは特に良い様に見えるが、この式はGoff-Gratch式を最小二乗近似したもので、August-Roche-Magnusの式の一種ではない。そのため、元の式よりは簡単であるがやや入力が多い(スクリプトは後に示した)。
氷点以下の飽和水蒸気圧に関しては、AE1995がかなり良い値を示していることが分かるだろう。
なお、Tetensのパラメータは氷点以下のものがよく分からなかったので組み込んでおらず、氷点以下の値は適切ではない。後述のスクリプトを見てもらえばわかるが、Tetensのパラメータはとても簡単で、しかも常用対数を使っている。対象とする温度範囲に氷点以下が含まれないのであればこのパラメータを用いても問題ないだろう。この桁数でこの当てはまりは驚異的であり、Tetensの式と呼ばれてきただけの事はある。

Rのスクリプト

グラフの描画に用いたスクリプトを記しておく。
ライブラリは以下のものを使用した。

library(tidyr)
library(ggplot2)

飽和水蒸気圧を求める式を定義する。AE1995は前述の通り。

GofGra <- function(t, s.cool=FALSE){
  # Goff-Gratchの式
  ifelse((t > 0) | s.cool, 
    10^ # 水または過冷却水(s.cool=TRUE)の場合(-50〜100度)
      (10.79574 * (1 - 273.16/(t + 273.15)) -
         5.02800 * log((t + 273.15)/273.16, 10) +
         1.50475 * 10^{-4} * {1-10^(-8.2969 * ((t + 273.15)/273.16 - 1))} +
         0.42873 * 10^{-3} * {10^(4.76955*(1 - 273.16/(t + 273.15))) - 1} +
         0.78614), 
    10^ # 氷上の場合(-100度まで)
      (-9.09685 * (273.16/(t + 273.15) - 1) -
         3.56654 * (log(273.16/(t + 273.15), 10)) + 
         0.87682 * (1 - (t + 273.15)/273.16) + 
         0.78614)
    )
}

Okada <- function(t, s.cool=FALSE){
  # 岡田の式(Goff-Gratch式を最小二乗近似したもの)
  ifelse((t > 0) | s.cool,
    exp(1.809378 + # 水または過冷却水の場合(-30〜50度)
          0.07266115 * t +
          (-3.003879 * 10^-4) * t^2 +
          (1.181765 * 10^-6) * t^3 +
          (-3.863083 * 10^-9) * t^4),
    exp(1.809378 + # 氷上の場合(-30度まで)
          0.08238957 * t +
          (-2.990908 * 10^-4) * t^2 +
          (1.362765 * 10^-6) * t^3)
  )
}

# August式のパラメータ違い
Murray <- function(t){
  ifelse(t > 0,
         6.1078 * exp(17.2693882 * t /(t + 237.3)),
         6.1078 * exp(21.8745584 * t /(t + 265.5))
         )
  }
Tetens <- function(t){ 6.11 * 10^(7.5*t/(t + 237.3)) }

プロット。tidyrパッケージを使うとプロットに適した形式への変換が簡単だった。

# 対象とする温度範囲
ts <- seq(-100, 100, 0.1)
# 相対誤差を計算しデータフレームを作成
es.diff <- data.frame(air.temp = ts,
                      Okada =  (Okada(ts) - GofGra(ts)) / GofGra(ts) * 100,
                      Murray = (Murray(ts) - GofGra(ts)) / GofGra(ts) * 100,
                      Tetens = (Tetens(ts) - GofGra(ts)) / GofGra(ts) * 100,
                      AE1995 = (AE1995(ts) - GofGra(ts)) / GofGra(ts) * 100)
# longフォーマットへの変換(tidyr使用)
es.diff.l <- gather(es.diff, "method", "diff", -air.temp)
# plot
theme_set(theme_gray(base_family="HiraKakuProN-W3")) # 日本語プロット用設定
ggplot(es.diff.l, aes(x = air.temp, y = diff)) +
  geom_line(aes(color = method)) + xlim(-100, 100) + ylim(-1, 1) +
  labs(title = "Goff-Gratchの式の値に対する相対誤差",
       y = "相対誤差(%)", x = "気温(℃)") 

ThinkPad X61 SSD化+その他いろいろ

2万ほど投資したらまだまだ使えそうな感じになった。

HDクローン作成

A-DATAのSSDを購入するとAcronis True image HDがダウンロードできるので、これを利用してHDのクローンを作成した。手順としては、

  1. Acronis True image HDの起動ディスクを作成
  2. シャットダウン(必要であればその後CD/DVDドライブからブートできるようにBIOS設定)
  3. SSDをケースに入れてUSB接続
  4. 外付けのCDドライブに入れてブート
  5. Clone ModeはAutomatic、SouceにHD、DestinationSSDを選択してスタート

これでSSDにデータがコピーされるので、終了したらHDとSSDを入れ替える。ついでにこのタイミングでメモリも入れ替えた。

Windows7 64bitのインストール

Windows10を入れる前に64bit化をした。Windows7のパッケージ版には32bit版と64bit版両方のインストールディスクが入っているが、このうち64bit版のインストールディスクを入れて新規インストールをした。新規インストールなので、一応データは退避されるが設定などは初期状態に戻る。
ここでWindows Updateを開始したところ全く終わらないので中止してWindows10のインストールを行った。

Windows10のインストール

GetWindows10から無償アップグレードというのが通常の手順だと思うが、これだと途中にWindows Updateが入ってくるのでそこで止まってしまって進まない。

  1. https://www.microsoft.com/ja-jp/software-download/windows10の下の方にある「ツールを今すぐダウンロード」からダウンロードできるインストールメディア作成ツールをダウンロード。
  2. ツールを使ってUSBフラッシュメモリをインストールメディアにする
  3. USBフラッシュメモリからWindows10をインストールする(USBフラッシュメモリからブートするわけではなく、Windows7上で実行する)

このとき、Windows Updateをするかどうか訪ねてくると思うが、これを後回しにすることでインストールを完了できる。

Windows10インストール後の設定

いまさらハック: Win10にアップグレードしたX220のTrackpointセンタースクロールをMetroアプリでも動かす方法)。

Ubuntu再インストール

ここまででWindowsは使えるようになったが、別パーティションに入れていたUbuntuが起動しなくなっていたのでインストールしなおした。

  1. Ubuntu Desktop 日本語 Remixのダウンロード | Ubuntu Japanese TeamからUbuntu 15.10のisoファイルを入手。
  2. UNetbootinUNetbootin, Universal Netboot Installer 日本語情報トップページ - OSDN)と上記のisoファイルを利用してUSBフラッシュメモリをインストールメディア化する。
  3. インストール(BIOS設定からUSB HDDの起動順位を上げる必要がある)

Windows標準のブートローダーを使用するようにする

ここまで行き当たりばったりでやった結果、起動するとgrubが立ち上がり、grubからWindows10を選択するとWindowsブートローダーが立ち上がるという面倒な状態になってしまったのでこれを修正する。

bootrec /fixboot 
bootrec /fixmbr
exit

ここまででgrubは起動しなくなる。次に、Windowsブートローダーの項目を修正する。

これで起動後はWindows標準のブートローダーが起動するようになる。そこからUbuntuを選択するとgrubが起動する。