R : POSIXctをas.Date() する時にtzを指定しない場合、POSIXctのタイムゾーンに何が設定されていてもUTCとみなして処理されているのでは?
POSIXct
はタイムゾーンを伴った日時型であり、これをas.Date()
という組み込み関数に渡すと、Date
という日時型に変換できる。
この関数の挙動にどうにも違和感がある。
どうもこの関数、POSIXctをas.Date() する時にtzを指定しない場合、POSIXctのタイムゾーンに何が設定されていてもUTCとみなして処理されている
ようなのだ。
例
> as.POSIXct('2015-01-01 00:00:00') [1] "2015-01-01 JST" > as.Date(as.POSIXct('2015-01-01 00:00:00')) [1] "2014-12-31" > as.Date(as.POSIXct('2015-01-01 00:00:00', tz="UTC")) [1] "2015-01-01"
実装を読んでみた
as.Date
はRにおいて、総称関数
と呼ばれるタイプの関数である。
これは、与えられた引数の型を判定して、型に応じて異なる処理を行う仕組みである。
この総称関数の実装を読むには以下のようにする。
> methods(as.Date) [1] as.Date.IDate* as.Date.POSIXct as.Date.POSIXlt as.Date.character as.Date.date as.Date.dates as.Date.default [8] as.Date.factor as.Date.numeric see '?methods' for accessing help and source code > as.Date.POSIXct function (x, tz = "UTC", ...) { if (tz == "UTC") { z <- floor(unclass(x)/86400) attr(z, "tzone") <- NULL structure(z, class = "Date") } else as.Date(as.POSIXlt(x, tz = tz)) } <bytecode: 0x5d0f708> <environment: namespace:base>
as.Date.POSIXct
のtz
にデフォルト引数として"UTC"
が指定されている。
function (x, tz = "UTC", ...)
これでは、引数のPOSIXct
のtz
がなんであれ、(as.Date()
のtz
が明示的に指定されない限り)"UTC"
として処理されてしまう。
(…と、読み取ったんですが合ってますかね? 何か見落としがあったら教えて下さい。)
現状のas.Date
のインターフェースデザインの課題
このようなAPIのデザインはフールプルーフの原則にのっとっていないと感じる。
この関数は、「as.Date()
を使う時はtz
を明示的に指定する必要がある」という認識を欠いた人に対して手痛い打撃を与えることになる。
もし自分が実装者だったら?
tz
を明示的に指定しない場合に例外を出すか、引数となったPOSIXct
のtz
を使用するようにする。- 今から変えたら後方互換性が凄い事になるので無理だろうけど…
自分もこういうデザインをしないように気をつけます…
ggplot2 ヒートマップの並び順を変更したい。
factorのlevels順に表示されるっぽいので、levelsを任意の順番に並び替えればできるらしい。できた。
R 「エラー: 関数 "grid.newpage" を見つけることができませんでした」と言われる
結論
library(grid)
する。
> # エラーになる > grid.newpage() エラー: 関数 "grid.newpage" を見つけることができませんでした > > # gridを読み込めば大丈夫 > library(grid) > grid.newpage()
説明
grid.newpage()
はggplot2
に含まれていない。
R data.tableから一定量のレコードをサンプリングしたい
結論
dplyr
つかう。
library(dplyr) dt %>% sample_n(100) # 100レコード取り出す dt %>% sample_frac(0.1) # 全レコードの10%を取り出す
R ある関数が現在のスコープに存在するか調べたい
結論
たとえばlibrary()
関数が現在のスコープに存在するか確認する場合:
target_function_name <- 'library' exists(target_function_name)
[R] キーワード付き引数みたいな事がしたい
- rubyで言うところのキーワード付き引数みたいな事がしたい。
結論
- 普通に引数を定義するだけで、キーワード付き引数のように振る舞う。
function_argument_biheibia_test <- function(argument1, argument2) { print(argument2) } function_argument_biheibia_test(argument2='test_message') # => "test_message"
[dplyr] group_byを行う時、集約に使うキーを変数で指定したい。
やりたい事
ここにiris
がある。
> head(iris) Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa
これをPetal.Width
でgroup_by
してn
をカウントしたい時はこうする。
> iris %>% group_by(Petal.Width) %>% summarise(n = n()) Source: local data frame [22 x 2] Petal.Width n 1 0.1 5 2 0.2 29 3 0.3 7 ...
今回は、Petal.Width
を使ってgroup_by
したが、これを動的に指定したい。
結論
group_by_
を使う + キーは変数に入れておく。
> group_by_key <- "Petal.Width" > iris %>% group_by_(group_by_key) %>% summarise(n = n()) Source: local data frame [22 x 2] Petal.Width n 1 0.1 5 2 0.2 29 3 0.3 7
このコードで言うところのgroup_by_key
に任意のカラム名を入れる事でgroup_by
に使うキーを動的に指定できる。