Skip to main content

Rで統計: CSVファイルの読み込み - read.csv()メソッド

· 3 min read
Yu Sasaki
Enterprise Security Manager / Advisor

読み込むCSVファイルは2007年度のセリーグの打撃成績の順位です。

参考:2007年度 セントラル・リーグ 個人打撃成績(規定打席以上)

batting2007.csv

順位,打率,安打
1,0.346,193
2,0.343,204
3,0.318,172
4,0.313,177
5,0.31,175
6,0.308,155
7,0.302,122
8,0.302,118
9,0.3,120
10,0.3,139

プロンプト

> read.csv("batting2007.csv")
順位 打率 安打
1 1 0.346 193
2 2 0.343 204
3 3 0.318 172
4 4 0.313 177
5 5 0.310 175
6 6 0.308 155
7 7 0.302 122
8 8 0.302 118
9 9 0.300 120
10 10 0.300 139
> batting$安打
[1] 193 204 172 177 175 155 122 118 120 139

read.csv()メソッドでCSVファイルを読み込み、そのデータフレームをbatting変数に格納しています。

実行結果を見ると、ファイル1行目のフィールド(列)名が変数名を表し、2行目以降がテーブル本体を表していることが分かります。これによって、例えば安打の列を抽出したい場合は、batting$安打と指定すればOKです。

ただ、毎回々々「batting$安打」と指定するのは億劫ですので、以下のコマンドで簡略化します。

> attach(batting)
> 安打
[1] 193 204 172 177 175 155 122 118 120 139
>

attach()関数によってワークスペースにオブジェクトが保存され、データフレーム内の変数名のみでのアクセスが可能になります。

read.csv()メソッドのheader引数にFALSEを指定した場合

read.csv()メソッドはデフォルトでheader引数にTRUEが指定されていますが、以下のようにFALSE(必ず大文字)を指定することも出来ます。その場合の動作は以下のようになります。

> batting <- read.csv("batting2007.csv", header=FALSE)
> batting
V1 V2 V3
1 順位 打率 安打
2 1 0.346 193
3 2 0.343 204
4 3 0.318 172
5 4 0.313 177
6 5 0.31 175
7 6 0.308 155
8 7 0.302 122
9 8 0.302 118
10 9 0.3 120
11 10 0.3 139
> batting$V3
[1] 安打 193 204 172 177 175 155 122 118 120 139
Levels: 118 120 122 139 155 172 175 177 193 204 安打
>

ファイル1行目の列名がテーブル本体のデータセットに組み込まれていることが分かります。この場合の列へのアクセスは上の実行結果から、batting$V3と分かります。フィールド(列)名(一行目)を省略したCSVファイルを読み込みたい場合にはこのオプション引数を指定します。

Rで統計: ヒストグラムの描画 - hist()関数

· 2 min read
Yu Sasaki
Enterprise Security Manager / Advisor

使用データは、ある30点満点のテストの20人分です。

19, 28, 4, 23, 8, 7, 20, 8, 12, 22, 19, 18, 14, 13, 13, 25, 12, 16, 11, 26

プロンプト

hist()関数の引数にベクトル変数を代入することでヒストグラムを描画できます。

> test <- c(19, 28, 4, 23, 8, 7, 20, 8, 12, 22, 19, 18, 14, 13, 13, 25, 12, 16, 11, 26)
> hist(test)
>

実行結果

30点満点テスト20人分の成績のヒストグラム

横軸が階級値で縦軸が度数(階級に入るデータ数)です。例えば、15**<x≦**20点の範囲の人が5人いる、と読めます。ただし、左端の0点データは0~5の階級に入ります。ここでは範囲の境界に注意しましょう(主に私が)。

データ作成に使用した乱数生成スクリプト

>>> import random
>>> [random.randint(0, 30) for i in range(20)]
[19, 28, 4, 23, 8, 7, 20, 8, 12, 22, 19, 18, 14, 13, 13, 25, 12, 16, 11, 26]
>>>

つい最近慣れ始めたPythonで書いてしまいました。リスト内包表記が地味に便利なところです。リスト内包表記についてはこちらをご覧ください。→Python: リスト内包表記をfor文に書き換える

そして、乱数モジュールの使い方に関してはこちらを、→Python: 乱数の生成 - random()、randint()、uniform()、seed()メソッド

また、重複のない乱数を生成するスクリプトはこちらをご覧ください。→Python: モジュールにテスト関数を定義 - 重複のない乱数(整数MIN以上MAX以下)の生成

Python: テキストファイルの行頭に行番号を追加

· One min read
Yu Sasaki
Enterprise Security Manager / Advisor

コマンドラインで指定されたテキストファイルの行頭に行番号を追加し、そのデータを新たなファイルに書き出すスクリプトです。

ソースコード

#!/usr/bin/python
# coding: UTF-8
import sys
argvs = sys.argv
argc = len(argvs)
if (argc != 3):
print 'Usage: $ python %s target_file making_file' % argvs[0]
quit()
f = open(argvs[1])
lines2 = f.readlines()
f.close()
nf = open(argvs[2], 'w')
i = 1
for line in lines2:
nf.write('%3d: %s' % (i, line))
i = i + 1
nf.close()

仮にこのソースコードをfile05a.pyというファイルで保存した場合、使用する際はプロンプトに以下のように打ち込みます。

実行結果

プロンプト

> python file05a.py file05a.py file05a-l.txt

この結果、生成されたファイルが下記になります。

file05a-l.txt

1: #!/usr/bin/python
2: # coding: UTF-8
3:
4: import sys
5:
6: argvs = sys.argv
7: argc = len(argvs)
8: if (argc != 3):
9: print 'Usage: $ python %s target_file making_file' % argvs[0]
10: quit()
11: f = open(argvs[1])
12: lines2 = f.readlines()
13: f.close()
14: nf = open(argvs[2], 'w')
15: i = 1
16: for line in lines2:
17: nf.write('%3d: %s' % (i, line))
18: i = i + 1
19: nf.close()

Rで統計: ベクトル変数に対する操作 - 複数データを一括処理

· 2 min read
Yu Sasaki
Enterprise Security Manager / Advisor

ベクトル変数は複数のデータを1つにまとめた変数で、他言語でいえば配列はリストに相当する機能を備えています。なので「[]」演算子によるベクトル変数の要素、スカラー値へのインデックス指定が可能です。今回はRのベクトル変数内の全要素に対する演算の例を取り上げます。

プロンプト

> vec1 <- c(1, 3, 5, 7, 9) # ベクトル変数の作成。「<-」演算子は代入
> vec1
[1] 1 3 5 7 9
> print(vec1 + 2)
[1] 3 5 7 9 11
> print(vec1 - 2)
[1] -1 1 3 5 7
> print(vec1 * 5)
[1] 5 15 25 35 45
> print(vec1 / 5)
[1] 0.2 0.6 1.0 1.4 1.8
>
> vec2 <- vec1 - 1
> print(vec2)
[1] 0 2 4 6 8
> print(vec1 + vec2) # ベクトル同士の演算
[1] 1 5 9 13 17

ベクトル変数名に対してそのまま演算子が使えるのが直感的で良いですね。

プロンプトを使用する際は、print()関数を使用しなくても、変数名のみで値を出力することが可能ですが、私はRファイルにprint()を書き残す習慣があるので、こちらでも付けてあります。

Rで統計: *.Rソースファイルの読み込みと実行 - source()関数

· 2 min read
Yu Sasaki
Enterprise Security Manager / Advisor

これまでの例は数行のコマンドでしたのでプロンプトに直接を打っていましたが、何十行というロジックをプロンプトに順々に打っていくのは非効率です。今回は、予め外部のテキストファイルにソースコードを書き、そのファイルをプロンプトから呼び出す手順を次の例で示します。

以下のソースコードを拡張子Rのテキストファイルで保存し、プロンプトから読み込んで実行してみましょう。

test.R

batting2007 <- c(193, 204, 172, 177, 175, 155, 122, 118, 120, 139)
print(batting2007)

このテキストファイルを作業ディレクトリにおきます。なお、作業ディレクトリの設定方法はこちらをご覧ください。→作業ディレクトリの設定と確認 - setwd()、getwd()関数

プロンプト

> source("test.R")
[1] 193 204 172 177 175 155 122 118 120 139
>

print()関数を用いて画面へ出力しています。

ここで、この状態のままプロンプトで以下のように入力すると、

> summary(batting2007)
Min. 1st Qu. Median Mean 3rd Qu. Max.
118.0 126.2 163.5 157.5 176.5 204.0
> mean(batting2007)
[1] 157.5
>

このように、読み込んだソースファイル中の変数が使えることが分かります。これは、関数宣言等を別ファイルに保存し、プロンプトから呼び出したい場合によく使います。

SafariとChromeでSyntaxHighlighterのPythonコードがハイライトされない問題の解決法

· 2 min read
Yu Sasaki
Enterprise Security Manager / Advisor

追記(2009-02-14): v2.0でこのバグは改善されていました。 先日「Google Chrome」ベータ版がリリースされましたね。私もV8のパフォーマンス興味に試してみたら速すぎて笑っちゃいました。ただ同時に、閲覧情報のプライバシーや利用規約の内容等が結構物議を醸していますね。

java.io.StreamCorruptedExceptionが発生した原因とその解決策の一例

· 3 min read
Yu Sasaki
Enterprise Security Manager / Advisor

以前というかこの頃Javaで簡単な分散処理サーバ・クライアントシステムのモデルを実装中にこのjava.io.StreamCorruptedExceptionという例外が発生。

StreamCorruptedExceptionの発生原因

結論から言えば、恐らく実行中のスレッドの数がマシンスペックに対して多すぎたのではないかと推定(推定どまり)。 サーバが複数のクライアントを受け付けるので、クライアントのソケット接続(accept時)毎にスレッドを生成する方法を採った。この時はブロッキング型のモデル(この頃ノンブロッキング型は知らなかった)。 例外の発生状況はサーバプログラムをテスト動作時、絶えず約1000クライアントからのリクエストを受け付け、かつレスポンス等を行った場合。なお送受信データはシリアライズされたオブジェクトで、サイズは平均5KB。その時テストマシンで走らせたスレッド数が約5000。 シリアライズの復元の問題かと考えたが、送受信するオブジェクトのクラスとそのserialVersionUIDは揃えており、500クライアント位ではこれといった異常なく動作していた。 実際にある時間のクライアントの送信データ数とサーバの受信データ数を確認してみたら、両数値の差が生じていて、約200リクエストがソケット部分で溜まったところでダウンしました。 スレッド数が多いと、その分スレッドの切り替えが頻発したり、待たされるスレッドが出てくる。その為、ソケットの部分で受信データが許容量以上に溜まって、I/Oのどこかがオバーフローか変になった可能性もある。

例外発生時のスタックトレースの一部抜粋

java.io.StreamCorruptedException: unexpected reset; recursion depth: 1
at java.io.ObjectInputStream.handleReset(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.skipCustomData(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)

また、これ以外にOptionalDataExceptionという例外も併発しましたが、これも同じ原因かと推定。

java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)

試した解決策

スレッド数を抑える

これは解決策とは言えないが、マシンスペック(CPU[コア]数やクロックなど)に対してスレッド数が多すぎるのが問題だと推定したので、ある程度スレッド数を抑えて運用したところ例外は発生しなくなった。

もう一度接続しなおす

例外をtry-catchブロックでキャッチできるので、それに合わせて接続しなおしてリクエストorレスポンスを再送することで一時対処した。

ノンブロッキング型にする

nio(New I/O)ライブラリが用意されているので、それを用いたノンブロッキング型の機構にして、スレッドプールを用意することでスレッド数やコンテキストスイッチ、オーバヘッドをある程度抑えることが可能と考えるが、まだ未検証。 どちらにせよ、根本原因の究明にはkernel dump等の情報を取って解析していく必要がある。。。

Rで統計: 作業ディレクトリの設定と確認 - setwd()、getwd()関数

· One min read
Yu Sasaki
Enterprise Security Manager / Advisor

プログラムからテキストやCSVファイル等を読み込む為にファイルパスの指定する際、ファイル名のみで読み込むホームディレクトリのことを作業ディレクトリといい、その設定方法は以下の2種類あります。

RGuiを使用している場合は、[ファイル]→[ディレクトリの変更]から任意のディレクトリを選択。

コマンドで変更する場合はプロンプトで、

> setwd("D:/rtmp")

の様に、setwd()関数の引数にディレクトリのパスを代入することで指定します。

また、作業ディレクトリを確認する関数はgetwd()です。

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

getwd は get work directoryの略かな。

あと、Windowsの場合は作業ディレクトリ設定を恒久的に保存する方法のひとつに、Rgui.exeのショートカットのプロパティの作業フォルダにパスを設定する方法があります。

Rで統計: データ集合中の最大、最小、平均、中央値 - summary()関数

· 3 min read
Yu Sasaki
Enterprise Security Manager / Advisor

使用するデータに2007年度のセリーグの打撃成績の1位~10位までの安打を用います。

参考:2007年度 セントラル・リーグ 個人打撃成績(規定打席以上)

順 位選 手安 打
1青木 宣親(ヤ)193
2ラミレス(ヤ)204
3谷 佳知(巨)172
4小笠原 道大(巨)177
5栗原 健太(広)175
6高橋 由伸(巨)155
7佐伯 貴弘(横)122
8相川 亮二(横)118
9赤星 憲広(神)120
10宮本 慎也(ヤ)139

上表より安打の基本統計量を求めるには以下のコマンドを使用します。

> summary(c(193, 204, 172, 177, 175, 155, 122, 118, 120, 139))
Min. 1st Qu. Median Mean 3rd Qu. Max.
118.0 126.2 163.5 157.5 176.5 204.0
>

1行目の「> 」以降の文字列がコマンドで2、3行目がその実行結果となり、実行結果の項目の意味はそれぞれ下表のようになります。

summary()関数の戻り値の意味

summary()意味
Min最小値
1st Qu第一四分位数
Median中央値
Mean平均値
3rd Qu第三四分位数
Max最大値

ここで、中央値とはデータ集合中の中央の順位に位置する値であり、第一四分位数と第三四分位数はそれぞれ、下から数えて1/4、3/4の順位に位置する値です。

ただし、データ個数が偶数個の場合は、中央(1/4、3/4)の順位に近い2つの値の算術平均をとります。

コマンドの説明

c()関数の引数に10人の安打数をカンマ区切りで代入し、戻り値として10人のデータをまとめたベクトル変数を得ます。summary()関数にそのベクトル変数を代入することで今回の実行結果を得ています。

ちなみに、c()の c は combine の頭文字からきています。

中央値と平均値の使い分け

平均値はデータ集合の散らばり具合が分かりませんので、その平均値がデータ集合全体を表すのに妥当かどうか判断できません(→散らばり具合は分散、偏差から分かる)。ただ、中央値によってそれをある程度補完することが出来ます。

仮に、上のデータに年間安打1000本の選手(現実そんなに打席に入れません>_<)を入れると

> summary(c(193, 204, 172, 177, 175, 155, 122, 118, 120, 139, 1000))
Min. 1st Qu. Median Mean 3rd Qu. Max.
118.0 130.5 172.0 234.1 185.0 1000.0
>

これによって平均値がかなり押し上げられていますが、中央値は1つずれただけですね。中央値はデータの個数と順序によって決まるものなので、突出したデータが少数入っていてもあまり影響は受けません。

最大値、最小値、平均値、中央値を求める関数(別個に)

ベクトル変数を以下のように設定したとき、

> batting2007 <- c(193, 204, 172, 177, 175, 155, 122, 118, 120, 139)

最大値、最小値、平均値、中央値はそれぞれmax()、min()、mean()、median()関数で求まります。

> max(batting2007)
[1] 204
> min(batting2007)
[1] 118
> mean(batting2007)
[1] 157.5
> median(batting2007)
[1] 163.5
>