web-dev-qa-db-ja.com

RでプロットするためにPOSIXctから時間と秒を抽出する

次の_data.frame_ fooがあるとします

_           start.time duration
1 2012-02-06 15:47:00      1
2 2012-02-06 15:02:00      2
3 2012-02-22 10:08:00      3
4 2012-02-22 09:32:00      4
5 2012-03-21 13:47:00      5
_

そしてclass(foo$start.time)は戻ります

_[1] "POSIXct" "POSIXt" 
_

_foo$duration_ v。_foo$start.time_のプロットを作成したいと思います。私のシナリオでは、実際の年の日ではなく時刻にのみ興味があります。ベクトルのPOSIXctクラスから時間:秒として時刻を抽出するにはどうすればよいですか?

56
andrewj

これは良い質問であり、Rで日付を処理する際の難しさの一部を浮き彫りにします。lubridateパッケージは非常に便利です。そのため、以下では2つのアプローチを示します。

元の投稿のデータフレーム(の最初の2行)を再作成します。

foo <- data.frame(start.time = c("2012-02-06 15:47:00", 
                                 "2012-02-06 15:02:00",
                                 "2012-02-22 10:08:00"),
                  duration   = c(1,2,3))

POSIXctおよびPOSIXtクラスに変換する(これを行う2つの方法)

# using base::strptime
t.str <- strptime(foo$start.time, "%Y-%m-%d %H:%M:%S")

# using lubridate::ymd_hms
library(lubridate)
t.lub <- ymd_hms(foo$start.time)

次に、時間を10進数の時間として抽出します

# using base::format
h.str <- as.numeric(format(t.str, "%H")) +
               as.numeric(format(t.str, "%M"))/60

# using lubridate::hour and lubridate::minute
h.lub <- hour(t.lub) + minute(t.lub)/60

これらのアプローチが同等であることを示します。

identical(h.str, h.lub)

次に、上記の方法のいずれかを選択して、foo$hr

foo$hr <- h.str

# If you prefer, the choice can be made at random:
foo$hr <- if(runif(1) > 0.5){ h.str } else { h.lub }

次に、ggplot2パッケージを使用してプロットします。

library(ggplot2)
qplot(foo$hr, foo$duration) + 
             scale_x_datetime(labels = "%S:00")
50
David LeBauer

ベースRに依存できます:

# Using R 2.14.2
# The same toy data
foo <- data.frame(start.time = c("2012-02-06 15:47:00", 
                                 "2012-02-06 15:02:00",
                                 "2012-02-22 10:08:00"),
                  duration   = c(1,2,3))

クラスPOSIXctには構造化された方法で日時情報が含まれているため、substrを使用して、POSIXctベクトル内の時間位置の文字を抽出できます。つまり、POSIXctの形式(印刷時にどのように表示されるか)がわかっていれば、時間と分を抽出できます。

# Extract hour and minute as a character vector, of the form "%H:%M"
substr(foo$start.time, 12, 16)

そして、任意の日付に貼り付けて、POSIXctに戻します。この例では2012年1月1日を使用していますが、日付を指定せずにformatを使用する場合、Rは現在の日付を使用します。

# Store time information as POSIXct, using an arbitrary date
foo$time <- as.POSIXct(paste("2012-01-01", substr(foo$start.time, 12, 16)))

そして、plotggplot2は両方とも、POSIXctで時間をフォーマットする方法を知っています。

# Plot it using base graphics
plot(duration~time, data=foo)

# Plot it using ggplot2 (0.9.2.1)
library(ggplot2)
qplot(x=time, y=duration, data=foo)
17
chemman

このコードは、文字列に変換して数値に戻すよりもはるかに高速です

time <- c("1979-11-13T08:37:19-0500", "2014-05-13T08:37:19-0400");
time.posix <- as.POSIXct(time, format = "%Y-%m-%dT%H:%M:%S%z");
time.Epoch <- as.vector(unclass(time.posix));
time.poslt <- as.POSIXlt(time.posix, tz = "America/New_York");
time.hour.new.york <- time.poslt$hour + time.poslt$min/60 + time.poslt$sec/3600;

> time;
[1] "1979-11-13T08:37:19-0500" "2014-05-13T08:37:19-0400"
> time.posix;
[1] "1979-11-13 15:37:19 IST" "2014-05-13 15:37:19 IDT"
> time.poslt;
[1] "1979-11-13 08:37:19 EST" "2014-05-13 08:37:19 EDT"
> time.Epoch;
[1]  311348239 1399984639
> time.hour.new.york;
[1] 8.621944 8.621944
8
user43392

Lubridateは時刻データを処理しないため、Hadleyはこのタイプのデータにはhmsパッケージを推奨しています。このような何かが動作します:

library(lubridate)
foo <- data.frame(start.time = parse_datetime(c("2012-02-06 15:47:00", 
                                 "2012-02-06 15:02:00",
                                 "2012-02-22 10:08:00")),
                  duration   = c(1,2,3))


foo<-foo %>% mutate(time_of_day=hms::hms(second(start.time),minute(start.time),hour(start.time)))

2つの潜在的な問題に注意してください-1)lubridateにはhmsと呼ばれる別の関数があり、2)hms :: hmsは引数をその名前で示された順序と逆の順序で取ります(そのため、ほんの数秒を指定できます)

6
andyyy