Hatena::ブログ(Diary)

My Life as a Mock Quant このページをアンテナに追加 RSSフィード Twitter

2014-07-21

POSIXctのベクトルをNAで初期化したい

| 10:43 | POSIXctのベクトルをNAで初期化したいを含むブックマーク

Sys.time関数は「日付+時刻」で表現される現在時刻をPOSIXct型で返してくれる。

> class(Sys.time())
[1] "POSIXct" "POSIXt" 

ただ、このPOSIXct型のベクトルを、欠損(NA)付で使おうと意図して以下のように書くと…

> x <- rep(NA, 3)
> x[2] <- Sys.time()
> x
[1]         NA 1405906690         NA

日時がシリアルの数値になってしまう。これを直すためにNAにas.POSIXct関数を噛ませて書くと

> x <- rep(as.POSIXct(NA), 3)
> x[2] <- Sys.time()
> x
[1] NA                        "2014-07-21 10:38:32 JST" NA   

となって欲しい形となる。

また、

を見ると

as.POSIXct(chracter())

ってのもありかな。

2014-07-20

Rの正規表現で文字列分割〜複数スペースの場合〜

| 21:02 | Rの正規表現で文字列分割〜複数スペースの場合〜を含むブックマーク

今までよくわかってなかったから、いっつもperl=TRUEのオプション指定して正規表現書いていたが、こうやって書けるんだなぁって話。

でいうところの

幾つかの名前付き文字クラスが予め定義されている(ロケール依存)。これらは実際は [ [:alnum:] ] のように、さらに鈎括弧に入れて使う。

の、「さらに鈎括弧に入れて使う」を見落としていたため動かない病に侵されていたようだ。

以下は、単にある文字列からスペースを全削除しつつ文字列をスペースで分割するっていうコード。

もちろんFoward-pipe演算子(%>%)を使うためにdplyrパッケージは必須だ。

> library(dplyr)
> c("ABC      EJDLK     ZZZ") %>% 
+   strsplit("[[:space:]]")
[[1]]
 [1] "ABC"   ""      ""      ""      ""      ""      "EJDLK" ""      ""      ""      ""     
[12] "ZZZ"  

おっと、これだとスペースがまばらに残ってしまうので、

> c("ABC      EJDLK     ZZZ") %>% 
+   strsplit("[[:space:]]+")
[[1]]
[1] "ABC"   "EJDLK" "ZZZ"  

こんな感じで書くのがよかろう。

2014-07-09

std::shared_ptrを噛ませても、親クラスに子クラスのオブジェクト突っ込める

| 05:59 | std::shared_ptrを噛ませても、親クラスに子クラスのオブジェクト突っ込めるを含むブックマーク

「あれ?これOKだったっけ?」という話の確認で、具体的には「Baseを継承したDerivedのshared_ptrをBaseのshared_ptrに入れれたっけな?」という。

よく考えると、これが出来ないとshared_ptr使って動的多態できなくなるので、出来て当たり前か…

↓サンプルコード、ちゃんと代入出来てる&コンパイル通る&欲しい結果になる。

#include <iostream>
#include <memory>
//適当な継承関係のあるクラス
class Base
{
public:
	void sayHello(){ std::cout << "Hello" << std::endl; }
};
class Derived : public Base{};
//Baseを引数にhelloと言わせる関数
void sayHello(const std::shared_ptr<Base> & b){ b->sayHello(); }
//main
int main()
{
	std::shared_ptr<Base> b(std::make_shared<Base>());
	std::shared_ptr<Derived> d(std::make_shared<Derived>());
	sayHello(b);
	sayHello(d);
	return 0;
}

2014-07-02

evalをlapplyしたい(以前もハマった気がする)

| 23:05 | evalをlapplyしたい(以前もハマった気がする)を含むブックマーク

通常、R言語の呼び出しオブジェクトの評価と言えばevalを使って

> eval(call("<-", substitute(a), 1:10))

なんて書くと変数aが現在の環境*1にアサインされるわけです。

これをリストでもやりたいぞとそういうことです。

まず以下のような"呼び出しオブジェクト"を要素に持つリストを作ります。

> x <- list(call("<-", substitute(a), 1:10), call("<-", substitute(aa), 1:10), call("<-", substitute(aaa), 1:10))
> x
[[1]]
a <- 1:10

[[2]]
aa <- 1:10

[[3]]
aaa <- 1:10

んで、これを評価(eval)してやると、今の環境(コンソール)に1-10までの連続した数値を要素として持つ変数a,aa,aaaが出来ることを期待するわけです。

> lapply(x, eval)
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

でも、これだとだめ。ls()関数オブジェクト一覧を拾ってきてもだめ。そもそも存在しないわけです。

で、「ハハーン、lapply内の環境に変数がアサインされてるんだなこれ」

って思って、現在の環境を渡すつもりで

> environment()
<environment: R_GlobalEnv>
> lapply(x, function(y)eval(y, envir=environment()))
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

と書いてもやっぱりだめ。

答えは以下の通りで、あらかじめちゃんとenvironment関数を評価しておいて、適当な変数としてとっておけと、

関数内部で取得する"現在の環境"はコンソールの環境とはならないだろと。そういうことです。

> env.current <- environment()
> lapply(x, function(y)eval(y, envir=env.current))
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[3]]
 [1]  1  2  3  4  5  6  7  8  9 10

これで現在の環境に変数a,aa,aaaがアサインされるので、以降、使える。

前にも嵌った気がするが思い出せん。

*1:environment()で取得

kartzkartz 2014/07/02 23:59 > 変数a,aa,aaaが出来ることを期待するわけです。
>> lapply(x, eval)

個人的には、こういうときは、lapply(x, eval.parent) を使っていますが、いろんなやり方があるものですね。

teramonagiteramonagi 2014/07/03 00:27 ありがとうございます。
どうするのがベストプラクティスなのかまったくわからずで毎回試行錯誤…

r-dr-rr-dr-r 2014/07/03 06:01 "<<-" とするのは悪魔的なのだろうか?

teramonagiteramonagi 2014/07/03 18:10 今回のケースだと"狙った環境”にアサインしたかったので、<<-ははなっから考えておりませんでしたわ…

2014-07-01

データフレーム(文字列)の頻度を可視化したい 〜エラーバーを添えて〜 with dplyr, ggplot2

20:36 | データフレーム(文字列)の頻度を可視化したい 〜エラーバーを添えて〜 with dplyr, ggplot2を含むブックマーク

の続きみたいなもん。

前回の記事では

> sample(letters[1:15], 100, replace=TRUE)
  [1] "j" "n" "a" "n" "a" "l" "l" "h" "d" "o" "l" "l" "c" "f" "m" "g" "c" "j" "h" "m" "a" "d" "m" "c"
 [25] "g" "h" "c" "h" "d" "d" "l" "m" "l" "b" "i" "e" "d" "g" "f" "h" "c" "j" "i" "a" "m" "f" "n" "f"
 [49] "e" "e" "o" "f" "b" "b" "g" "m" "n" "h" "k" "g" "g" "b" "i" "d" "e" "n" "b" "h" "o" "a" "b" "m"
 [73] "n" "j" "b" "j" "h" "a" "h" "g" "k" "e" "f" "c" "c" "n" "e" "l" "k" "n" "i" "o" "f" "g" "o" "j"
 [97] "g" "c" "c" "f"

というデータの可視化を行ったが、今回はこれを

  • 複数回繰り返して(GROUP化するイメージ)
  • 各GROUP内での各文字の出現頻度を計算して
  • 各GROUP間での各文字の出現頻度の相対誤差を計算して
  • その結果を棒グラフ(出現頻度の平均) with エラーバー(相対誤差)で描画したい

という状況を考える。ややこしいですね。

サンプルデータを上に倣って適当に作ると

x <- data.frame(VALUE=sample(letters[1:15], 100, replace=TRUE), 
           GROUP=sample(1:10, 100, replace=TRUE))

な感じ。以下のようなデータになっている。

> head(x, 10)
   VALUE GROUP
1      l    10
2      d     2
3      f    10
4      m    10
5      h     3
6      d     3
7      d     1
8      i     1
9      l     3
10     a     6

好きな文字(A-O)を100個選んで、それを適当に10(GROUPのMAX値)個のグループに分けたデータということだ。

んで、上記の内容を一発でChain(%>%)するために以下のようなコードを書いた。

キモは

  • prop.tableでtableの結果を頻度に倒せる
  • geom_barの引数のstat="identity"は必須で、デフォルトでは"bin"になっており、これはデータのカウントに相当

としてる所だろうか。特にprop.tableは初めて知った。頻度出すのにはこれかー。

もっといいやり方はあると思うので、誰か頼む。

x %>% 
  group_by(GROUP) %>% 
  table %>% 
  prop.table(., 2) %>%
  data.frame %>%
  group_by(VALUE) %>% 
  summarize(MEAN=mean(Freq), SE=sd(Freq)/sqrt(n())) %>%
  ggplot(data=., aes(x=VALUE, y=MEAN)) +
  geom_bar(aes(fill=VALUE), stat="identity") + 
  geom_errorbar(aes(ymin=MEAN-SE, ymax=MEAN+SE), width=.5, size=2)

結果は↓、結構びゅーちふる。

f:id:teramonagi:20140701202756p:image

参考

パッケージなしでエラーバー描く関数の話。

シミュレーション結果(散布図)の正解線重ね描き〜エラーバーを添えて〜 - My Life as a Mock Quant