Hatena::ブログ(Diary)

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

2014-07-23

引数で渡した値が数値に変換可能かどうか調べる関数

| 20:08 | 引数で渡した値が数値に変換可能かどうか調べる関数を含むブックマーク

ググってもひっかからなかったので、自作。警告メッセージをsuppressWarnings関数で止めてるのがミソ。

このくらい、既存のRの関数でもあるんじゃないかなーどっかにあるんじゃないかなー(チラッチラッ

could_be_numeric <- function(value){!is.na(suppressWarnings(as.numeric(value)))}

使用例

> could_be_numeric(123)
[1] TRUE
> could_be_numeric("123")
[1] TRUE
> could_be_numeric("ABC")
[1] FALSE

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())

ってのもありかな。


同じように文字列ベクトルもNA初期化したい。元々のrep(NA, 3)という表現の型を見てみると

> class(rep(NA,3))
[1] "logical"

のようにlogical判定されているので、これをなんとかcharacterにしたいというわけだ。これも素直にas.character関数をかませれば

> class(rep(as.character(NA),3))
[1] "character

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

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 今回のケースだと"狙った環境”にアサインしたかったので、<<-ははなっから考えておりませんでしたわ…