| Top Page | プログラミング | R 自動化 目次 | 索引 | 前へ | 次へ |

R でプログラミング:データの一括処理とグラフ描き

3. ひとつのファイルのデータの処理

前のページで,ひとつのデータファイルの内容を読み込んで,データフレームにしまいました. それから,データフレーム中の特定のデータを指定する方法をいろいろ試してみました. このページでは,データフレームを使って簡単な計算をしてみます. そしてその結果をファイルにしまう方法を紹介します.

簡単な統計計算

平均などを計算させる

まえのページで使ったのと同じ,len_width.txt のデータを使います. これを

d <- read.table('len_width.txt', header 2015) 

でデータフレームに読み込んであるとします. まずはほんとに簡単な関数,何個のデータがあるかを求める length, 平均を計算する mean, 分散(標本分散でなく不偏分散)を計算する var, 中央値を計算する median を使ってみます. d にしまったデータフレームの1列め,len という名前の列をわたしてみましょう. # のうしろに説明が書いてあります. # からあとは命令として解釈されず,無視されますから, この部分は入力してもしなくても同じです.

length(d$len)  #  データの個数(ベクトルの要素数)
mean(d$len)    #  算術平均
var(d$len)     #  分散
median(d$len)  #  中央値

コピーするなり手で入力するなりして,どんな答えがかえってくるかたしかめてください.


相関関係を計算させる:いくつもの情報を含んだ計算結果

R には, meanvar のようにひとつの値を計算結果として返す関数のほか, いろいろなデータのかたまりを返してくれる関数があります. とくに統計解析関係にはそのような関数がたくさんあります. まずはひとつだけ例を見てみましょう.

ためしてみるのは cor.test です.この関数は, 同じ数の要素を含むベクトル2つを引数として受けとり,これらのデータセット間の 相関関係を調べるものです.相関係数のほか,相関係数の 95% 信頼区間や,p値(*) を計算してくれます.

※この場合は,ふたつのデータセットの母集団がたがいに独立に それぞれ正規分布にしたがうとき,このデータセットが示すような 相関係数ないしはそれより絶対値が大きな相関係数が偶然得られる確率. この値が小さいほど,得られた相関関係が偶然によるものとは考えにくいということ.

入力画面でcor.testを呼び出して,どんな計算結果が表示されるか見てみましょう.

cor.test(d$len, d$width)

と入力すると,

        Pearson's product-moment correlation

data:  d$len and d$width 
t = 3.866, df = 48, p-value = 0.0003322
alternative hypothesis: true correlation is not equal to 0 
95 percent confidence interval:
 0.2417142 0.6741840 
sample estimates:
      cor 
0.4872776 

というような結果が表示されるでしょう. d$len と d$width の相関係数は 0.4872776 で,95%信頼区間は [0.2417142, 0.6741840], また p値は 0.0003322 であることがわかります.

cor.test が返す結果はひとつのオブジェクト(データのあつまり)です. これを変数に代入することもできます.

cor.test(d$len, d$width) -> c.result
c.result

とすると,前と同じものが表示されるでしょう. 上の例では 左辺の評価結果を右辺の変数に代入する 代入演算子 -> を使ってます.左右が入れ替わったほかは,<- とまったく同じ機能です.

ところで,このページが目指すのは,プログラムを書いて多量のデータを 一括処理することでした. たくさんのデータについて相関関係を計算して,その結果をどんどん ファイルに記録したいとき,うえのような形式でしか出力できないのでは不便です. まだ,グラフのなかに必要な数値だけ書き込むなんてことも自動でやりたい作業です. cor.test が計算結果として返すオブジェクトのなかから, 個々のデータの値を取り出す必要ことができれば,プログラムでできることの 幅が大きくひろがりそうです.

一般に,データを集めたオブジェクトでは,個々のデータに名前をつけることが可能です. 関数が計算結果をオブジェクトのかたちで返すとき,個々のデータを呼び出せるように, それぞれ意味のある名前がつけられているのがふつうです. あるオブジェクトがどんな名前付きデータを含んでいるかは, names という関数で調べられます.

まずは cor.test が返すオブジェクトを調べてみましょう. さきほどの c.result を names に渡すと,

[1] "statistic"   "parameter"   "p.value"     "estimate"    "null.value" 
[6] "alternative" "method"      "data.name"   "conf.int"   

というような結果が表示されるはずです.

help(cor.test)で表示される詳細な説明のなかの value のところに, これらがそれぞれどんなデータなのか書かれています.相関係数の推定値は estimate, 信頼区間は conf.int,p値は p.value という名前がついていることなどが分かります.

あるオブジェクト名と,そのオブジェクトが持っているデータの名前とを $ をはさんで つなげると,そのデータそのものを指定することができます.

c.result$estimate
c.result$conf.int
c.result$p.value

などと入力してためしてください. このなかで,c.result$conf.int と入力すると,

[1] 0.2417142 0.6741840
attr(,"conf.level")
[1] 0.95

のように表示されたはずです.これは,信頼区間の下限と上限2つの値, そしてこの信頼区間のデータに加え conf.level という名前の属性があって, 0.95 という値が設定されている,ということまでを示しています. 属性というのは,オブジェクトが持っている付加情報のようなものです.

なにやら複雑になってきましたが,これらのデータを単独でとりだす方法を 書いておきます.

c.result$conf.int[1]  #  信頼区間の下限
c.result$conf.int[2]  #  信頼区間の上限

# c,result$conf.int の, conf.level という属性の値

attr(c.result$conf.int, 'conf.level')

attr 関数は,あるオブジェクトがもつ,ある属性の値にアクセス するための関数です. attr(c.result$conf.int, 'conf.level') は,c.result$conf.int が持っている conf.level という属性を表します.

R には,cor.test のように古典的で単純な統計計算だけでなく, さまざまな統計手法の関数が用意されています. それらの関数の使い方をしらべるときは,どのようにデータを与えたり オプションを指定したらよいかを見るだけでなく,どのようなオブジェクトの形で 結果を返すのかを見ることも必要です.

<練習>

計算結果をファイルに記録する

ファイル出力に使う関数

入力画面で作業する場合,画面に表示された結果をコピーしてほかのファイルに 貼り付ければ保存することができます. でも,これでは大量データの一括処理には向きません. 自動的にファイルへ書き込めたほうが便利にきまっています.

ファイルにデータを書き込むにはいくつかの方法があります. そのために使える関数を別表に まとめました(> テキストデータのファイル出力に関係する関数の例).

これらの関数を目的に応じて使い分ければよいのですが, たくさんの計算結果を一定の書式でファイルに書き出したい場合には, sprintfcat の組み合わせが使いやすいでしょう. また,作業の途中であっちのファイルに書込んだりこっちのファイルに書込んだり といった作業をしたいときには,複数のファイルへの窓口を用意して それを必要に応じて writeLine に渡す方法が便利です.

sprintf と cat でファイル出力

簡単な統計計算の結果を書き込む例を書いてみます.

x <- sprintf("mean\t%.3f\n", mean(d$width))  # \t はタブ記号
cat(x, file = "result.txt", append = TRUE)
x <- sprintf("var\t%.3f\n", var(d$width))
cat(x, file = "result.txt", append = TRUE)

cat は最後に改行してくれないので, sprintf の書式指定文字列の最後に \n という 改行(\n) を入れてあります. また,項目名と数値データのあいだにはタブ(\t) を入れてあります.

書式指定の書き方は,C や Perl の printf とほぼ同等です. sprintf直後の文字列が書式を指定する文字列,そのうしろに 出力したいものを並べます.文字列中に複数の書式指定がある場合,最初の 指定は最初の変数の出力を指定し,2番めの指定は次の変数の出力に, というふうに順番に適用します.

おもな書式指定をあげておきます.

書式を指定して文字列を生成してくれる sprintf は,ファイルへの出力データを 整形するのに有用なだけでなく,グラフ中に書き込む文字列を作るときや, 多数のファイルを一括処理するときに入力ファイル名や出力ファイル名を 自動的に生成するときにも活躍します.ぜひ,使い方に慣れておきましょう.

<練習>

まとめて関数に

ここまでの知識をつかって,簡単な統計計算の結果をファイルに書き込む関数を書いてみます.

#  数値データのベクトルを受けとり,データ数,平均,分散を計算して,
#  指定されたファイルに出力する関数

output.mean.var <- function(x, file.name)
{
    n <- length(x)  #  何個のデータがあるか.
    m <- mean(x)    #  平均
    v <- var(x)

    #  変数 s に,出力したいデータが並んだ文字列を記録する.
    s <- sprintf("%d\t%.4f\t%.4f\n", n, m, v)  # 平均と分散は小数4ケタで.

    #  指定ファイルに書き出し.append =T で追加モード.
    # なにも指定しないと append = FALSE と想定され,前のデータに上書きされてしまう.

    cat(s, file = file.name, append =T)  
}

上の例では,sprintf の出力を一度 s という変数に記録していますが, 下のように,cat の引数のところに 直接 sprintf() を書いてもかまいません.

...
    cat(sprintf("%d\t%.4f\t%.4f\n", n, m, v), file = file.name, append =T)  
...

ただし,一行にあまりたくさんのことを詰め込んで書くと あとで読みにくくなります. 私は,迷ったらいったん変数にしまうことにしています.

上のプログラムを書き込んだプログラムファイルを作り,適当な名前をつけます (たとえば output_mean_var.R). つぎに,R の入力画面から source を使ってこのファイルを読み込みます. (たとえば source('output_mean_var.R') のように). この関数はデータが並んだベクトルと出力ファイル名を必要としているので, それらを引数として渡して関数を呼びます.

output.mean.var(d$width, 'result.txt')

これで,現在の R の作業ディレクトリに result.txt というファイルが作られるはずです. ファイルがあるのを確認したら,エディタで中を見てみましょう. 内容は期待したとおりのものでしょうか?

<練習>

計算結果を任意の書式でファイルに記録する

多くの統計計算関数はいろいろなデータを含んだオブジェクトを返すことは すでに見ました. print 関数を使うと計算結果オブジュクトの要約を 適当なかたちで表示・出力させることができますが, 必要なデータだけを,自分が望むような形式にそろえて書き出すには 不向きです.

計算結果がしまわれたオブジェクトから個々のデータの値を表示させられる 方法はすでに説明しました.この方法を使って,二組のベクトルを受けとり, それらのあいだの相関係数,信頼区間の下限,上限,信頼レベル(95% とか 99%とか), そして p 値という5つの値を一行にタブ区切りで並べて出力する関数を書いてみます.

my.cor.test<- function(x1, x2, file.name)
{
    c.result <- cor.test(x1, x2)
    r <- c.result$estimate        #  相関係数
    r.lo <- c.result$conf.int[1]  #  相関係数の信頼区間の下限
    r.hi <- c.result$conf.int[2]  #  上限
    level <- attributes(c.result$conf.int)$conf.level
    p <- c.result$p.value         #  p 値
    result <- sprintf("%.4f\t%.4f\t%.4f\t%.4f\t%.4f\n", r, r.lo, r.hi, level, p)
    cat(result, file = file.name, append =T)  
}

これを適当な名前のファイルに書き込み,sourceで読み込んでから,

my.cor.test(d$len, d$width, 'test_result.txt')

などとすれば,test_result.txt というファイルに計算結果が記録されるはずです.

<練習>

<さらに練習>

(仮)プログラムのまちがい探し

人はかならずまちがえます。プログラムを作るときも、当然のようにまちがえます。 売り物のソフトウェアでも、完成までの作業工程のうち、何割もの時間がテスト (まちがい探し)と見つけたまちがいの修正に充てられます。 プログラミングの作業では、まちがいを効率よく見つけて修正することも重要な技術です。

というわけで、R プログラミングでのありがちなミスや、ミスの効率のよい見つけ方の 説明を用意したいのですが、まだできていません。ただ、こうした技術はどの プログラミング言語でも基本は共通です。まずは私の Perl の入門ページに書いた、 プログラムのまちがい,データのまちがい にも参考になる点が多いことと思います。 ぜひ眺めてみてください。 おいおい、このページの R 版を作成する予定です。

なお、ここで唐突にこんな節があるのには一応の理由があります。 期待したように動かないプログラムのまちがいを探すとき、 計算の途中経過を出力させながら、どこまでは正常に動作しているかを 確認するというのが基本ワザです。 この章では出力関数 cat を紹介したので、 ちょうどよい頃合いだと考えて、まちがい探しの節を仮に置いてみました。


| Top Page | プログラミング | R 自動化 目次 | 索引 | 前へ | 次へ |