ggplot2でx軸にPOSIXct型を使う

ggplot2のscale_x_datetime()とscalesのdate_format()を組み合わせるといい感じに軸の書式を設定できる。

サンプルデータ

> x <- as.POSIXct(c("2016-11-07 19:00:00 JST", 
                    "2016-11-07 20:00:00 JST"))
> y <- c(1, 2)
> df <- data.frame(Time = x, Value = y)
> df
                 Time Value
1 2016-11-07 19:00:00     1
2 2016-11-07 20:00:00     2

プロット

  • 目盛間隔を10分、時刻の形式をHH:MM:SSにする

scale_x_datetime()において、date_breaksに"10 mins"を、labelsにdate_format()を指定する。date_format()ではデフォルトのタイムゾーン(引数tz)が"UTC"になっているので注意する必要がある。日本時間を使う場合は"Asia/Tokyo"を指定する。

    • tz = "Asia/Tokyo" とした場合
> p <- ggplot(df, aes(x = Time, y = Value))
> p + geom_point() + 
      scale_x_datetime(date_breaks = "10 mins", 
                       labels = date_format(format = "%H:%M:%S", 
                                            tz = "Asia/Tokyo"))

f:id:umanohoneo:20161108001412p:plain

    • tz を指定しない場合 (tz = "UTC")
> p <- ggplot(df, aes(x = Time, y = Value))
> p + geom_point() + 
      scale_x_datetime(date_breaks = "10 mins", 
                       labels = date_format(format = "%H:%M:%S"))

f:id:umanohoneo:20161108002733p:plain

LinuxでCPUのクロック周波数を確認する

クロック周波数の仕様値を確認する

クロック周波数の仕様値を確認するには、/proc/cpuinfoのcpu MHzを確認する。コアごとの情報を確認できる。2コアの場合は以下のように表示される。

$ cat /proc/cpuinfo | grep "cpu MHz"
cpu MHz         : 3407.999
cpu MHz         : 3407.999

ただし、実際にはCPUがcpuinfoどおりのクロック周波数で動作しているとは限らない。例えば、省電力機能が有効ならクロック周波数は仕様値よりも下がっていることがほとんどだ。

実際のクロック周波数を確認する

実際のクロック周波数を確認するには、sar -mコマンドを使う。sysstatパッケージのバージョンによってシンタックスが異なるので注意する必要がある。1秒単位で瞬間的なクロック周波数を(無限に)出力するコマンドを以下に示す。今回は、時刻の形式をHH:MM:SSにするために、頭にLANG=Cをつけてsarを実行している。

$ LANG=C sar -m 1
Linux 2.6.32-642.1.1.el6.x86_64 (localhost.localdomain)         11/06/16        _x86_64_        (2 CPU)

23:50:20        CPU       MHz
23:50:21        all   3407.99
23:50:22        all   3407.99
23:50:23        all   3407.99
^C
$ LANG=C sar -m CPU 1
Linux 3.10.0-327.el7.x86_64 (localhost.localdomain)     05/25/16        _x86_64_        (1 CPU)

09:19:03        CPU       MHz
09:19:04        all   3407.99
09:19:05        all   3407.99
09:19:06        all   3407.99
^C

09:19:06        all   3407.99
Average:        all   3407.99

[Ctrl]+[C]で止めたときに平均値が出力される/されないの違いがある。

data.tableをggplot2で扱いやすい構造に変換する

ggplot2で複数の系列をプロットする際、データを保持するdata.tableオブジェクトが扱いにくい構造をとっていることがある。

ggplot2で扱いにくい構造

例えば、以下のように表側の要素(Timestamp)と表頭の要素(Key1もしくはKey2)で観測値(a~f)が定まるようなケースだ。この場合、系列Key1の折れ線グラフと系列Key2の折れ線グラフを描画しようとすると、各系列に対してgeom_line()を実行する必要がある。系列が増えると厄介だ。

  • 元のdata.tableオブジェクト(dataTable)
Timestamp| Key1| Key2
---------+-----+-----
        1|    a|    b
        2|    c|    d
        3|    e|    f

扱いやすい構造に変換

このようなときは、data.tableをmelt()してやればよい。dataにdata.tableオブジェクトを、id.varsにidとなる列を指定する(ベクトル型で複数指定可)。ここでidとは、RDBの世界で言うところの主キーである。

moltenDataTable <- 
    melt(data = dataTable, id.vars = "Timestamp")

melt()されたdata.tableオブジェクトの構造は以下のようになる。1レコード1観測値の構造となる。

  • melt()されたdata.tableオブジェクト(moltenDataTable)
Timestamp|Variable|Value
---------+--------+-----
        1|    Key1|    a
        1|    Key2|    b
        2|    Key1|    c
        2|    Key2|    d
        3|    Key1|    e
        3|    Key2|    f

melt()に伴う強制的な型変換

なお、melt()する際に各系列のデータ型が異なると、一定の規則に従って型変換が行われる。その際は警告メッセージが出力される。
警告メッセージを出さないようにするには、melt()する前に明示的に型変換を行う。以下は各列をdouble型に変換する例である。

dataTable <- dataTable[, lapply(.SD, as.double), by = Timestamp]

Linuxでsudoを使えるようにする

Linuxでsudoを使えるようにするには、以下の2つを実施すればよい。

  • ユーザをwheelグループに所属させる
  • wheelグループのユーザがsudoを使えるようにする

以下、honeoユーザを例にとって説明する。

ユーザをwheelグループに所属させる

gpasswdコマンドもしくはusermodコマンドを使う。おすすめはgpasswd。usermod -Gで補助グループを指定する場合は、既存の補助グループも含めてカンマ区切りで補助グループを列挙しなければならない。さもないとhoneoが既存の補助グループから外れてしまう。

# gpasswd -a honeo wheel
もしくは
# usermod -G wheel[,既存の補助グループ] honeo

wheelグループのユーザがsudoを使えるようにする

visudoコマンドで/etc/sudoersを編集する。

# visudo

以下のようにwheelグループの権限を設定している行のコメントアウト(行頭の#)を外す。

  • 変更前(CentOS 6.8のデフォルト)
## Allows people in group wheel to run all commands
# %wheel  ALL=(ALL)       ALL
  • 変更後
## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

設定の意味は以下のとおり。

%wheel
wheelグループに所属するユーザは
1つ目のALL
任意のホストで
2つ目のALL
任意のユーザとして
3つ目のALL
任意のコマンドを

実行できる。

設定変更が適用されるタイミング

設定変更は次回ログインから適用される。既存のセッションで以下のようにsu -してもよい。

$ su - honeo

CentOSにEPELパッケージをインストールする

マシンアーキテクチャとメジャーバージョンの確認

2016-11-04時点でEPELはバージョン5、6、7の3つが公開されている。マシンのアーキテクチャCentOSのメジャーバージョンに応じたEPELパッケージをインストールする必要があるので、はじめにその2点を確認する。

$ uname -r
2.6.32-642.1.1.el6.x86_64
$ cat /etc/centos-release 
CentOS release 6.8 (Final)

アーキテクチャx86_64、メジャーバージョンは6であることが分かった。この場合、対応するEPELパッケージは次のURLで取得できる。
http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm

パッケージ情報の確認

インストールする前にパッケージの情報を確認する。この作業は必須ではないが、仕組みを理解するために読んでおいたほうがよい。

$ rpm -qip http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
警告: http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY
Name        : epel-release                 Relocations: (not relocatable)
Version     : 6                                 Vendor: Fedora Project
Release     : 8                             Build Date: 2012年11月04日 19時54分41秒
Install Date: (not installed)               Build Host: buildvm-05.phx2.fedoraproject.org
Group       : System Environment/Base       Source RPM: epel-release-6-8.src.rpm
Size        : 22169                            License: GPLv2
Signature   : RSA/8, 2012年11月05日 07時29分49秒, Key ID 3b49df2a0608b895
Packager    : Fedora Project
URL         : http://dl.fedoraproject.org/pub/epel/
Summary     : Extra Packages for Enterprise Linux repository configuration
Description :
This package contains the Extra Packages for Enterprise Linux (EPEL) repository
GPG key as well as configuration for yum and up2date.

Descriptionを直訳するとこうだ。

このパッケージにはEPELリポジトリのGPGキーと
yum及びup2dateの設定が含まれる。

続いて、パッケージに含まれるファイルを確認してみる。

$ rpm -q --filesbypkg -p http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
警告: http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY
epel-release              /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
epel-release              /etc/rpm/macros.ghc-srpm
epel-release              /etc/yum.repos.d/epel-testing.repo
epel-release              /etc/yum.repos.d/epel.repo
epel-release              /usr/share/doc/epel-release-6
epel-release              /usr/share/doc/epel-release-6/GPL

yumからEPELリポジトリを参照するための.repoファイルが含まれていることが分かる。

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

ここまで理解したところで、いよいよパッケージをインストールする。なお、sudoコマンドが使えない場合は先に Linuxでsudoを使えるようにする - honeotech を実施する(su -でもいいけど)。

$ sudo rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm を取得中
警告: /var/tmp/rpm-tmp.QuYubc: ヘッダ V3 RSA/SHA256 Signature, key ID 0608b895: NOKEY
準備中...                ########################################### [100%]
   1:epel-release           ########################################### [100%]

yum repolist [enabled]コマンドで、yumが有効と認識しているリポジトリを表示し、EPELが有効となっていることを確認する(enabledは省略可)。

$ yum repolist
読み込んだプラグイン:fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
epel/metalink                | 5.5 kB     00:00
 * base: ftp.iij.ad.jp
 * epel: ftp.riken.jp
 * extras: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
epel                         | 4.3 kB     00:00
epel/primary_db              | 5.9 MB     00:00
リポジトリー ID    リポジトリー名                                    状態
base               CentOS-6 - Base                                    6,696
epel               Extra Packages for Enterprise Linux 6 - x86_64    12,214
extras             CentOS-6 - Extras                                     62
updates            CentOS-6 - Updates                                   581
repolist: 19,553

GPGキーのインポート

GPGキーをインポートする。これでパッケージの署名確認ができるようなり、rpmコマンドを打つ度に出ていた警告メッセージが出なくなる。

$ sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
# 何も出力されない

epelリボジトリの無効化(任意)

このままだとyumしたらデフォルトでepelレポジトリが参照されてしまうので、yum-config-manager --disableコマンドでepelリポジトリを無効化する。このあたりの設定はお好みで。
コマンドを実行すると、以下のように指定したリポジトリの設定が表示される。enabled=0(無効)となっていればOKだ。

$ sudo yum-config-manager --disable epel
読み込んだプラグイン:fastestmirror, refresh-packagekit
====================================== repo: epel =======================================
[epel]
bandwidth = 0
base_persistdir = /var/lib/yum/repos/x86_64/6
baseurl = 
cache = 0
cachedir = /var/cache/yum/x86_64/6/epel
cost = 1000
enabled = 0
# 以下省略

再度yum repolistコマンドを実行して、epelレポジトリが無効化された(表示されない)ことを確認する。

$ yum repolist
読み込んだプラグイン:fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
 * base: ftp.iij.ad.jp
 * extras: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
リポジトリー ID                         リポジトリー名                              状態
base                                    CentOS-6 - Base                             6,696
extras                                  CentOS-6 - Extras                              62
updates                                 CentOS-6 - Updates                            581
repolist: 7,339

無効化したリポジトリを参照するには、--enablerepoオプションを使う。

$ yum --enablerepo=epel info R.x86_64

Linuxでサイコロを振る

sortコマンドの-Rオプションを利用してランダム性を与える。

$ seq 6 | sort -R | head -1
3

bashならseqの部分を次のように書いてもよい。

$ echo {1..6} | xargs -n 1 | sort -R | head -1
5

ばらつきを確かめるために、10,000回実行してみる。
ついでに頭にtimeコマンドを付けて所要時間を測る。

$ time for i in `seq 10000`; do seq 6 | sort -R | head -1 >> dice.out; done

real	0m11.360s
user	0m0.043s
sys	0m3.454s

uniqコマンドの-cオプションを利用してヒストグラムを作る。

$ cat dice.out | sort | uniq -c
   1631 1
   1718 2
   1637 3
   1654 4
   1651 5
   1709 6

検証環境は以下のとおり。

$ uname -r
2.6.32-642.1.1.el6.x86_64
$ rpm -qf `which sort`
coreutils-8.4-43.el6.x86_64
$ rpm -qf `which uniq`
coreutils-8.4-43.el6.x86_64

おまけ

bashの組み込み変数RANDOMを使う手もある。RANDOMは参照されるたびに0~32767(32,768パターン)の整数をランダムに返す。

$ echo $(($RANDOM%6+1))
6

ただし、このサイコロの各目が出る確率は異なる。32,768は6で割り切れないためだ。剰余が2なので、1と2が他の目よりほんのちょっと出やすいはず。

$ for i in `seq 0 32767`; do echo $(($i%6+1)); done | sort | uniq -c
   5462 1
   5462 2
   5461 3
   5461 4
   5461 5
   5461 6

実際に1,000万回振ってみる。

$ time for i in `seq 10000000`; do echo $(($RANDOM%6+1)); done | sort | uniq -c
1665407 1
1665933 2
1666690 3
1667355 4
1667291 5
1667324 6

real	1m40.431s
user	1m13.327s
sys	0m28.025s

思ったとおりにならない。試行回数が少ないのか、確率分布が離散一様分布でないのか…

LinuxでCPUに負荷をかける

LinuxでCPUに負荷をかける場合、ddコマンドを使うとよい。

$ dd if=/dev/zero of=/dev/null

ddコマンド1プロセスで1コアに100%の負荷がかかる。マルチコアプロセッサでCPU使用率を100%にしたければ、ddコマンドをコアの数だけ実行すればよい。

検証環境は以下のとおり。

$ uname -r
2.6.32-642.1.1.el6.x86_64
$ rpm -qf `which dd`
coreutils-8.4-43.el6.x86_64