[英]extract hours and seconds from POSIXct for plotting purposes in R
假設我有以下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
foo$start.time
。 在我的場景中,我只對一天中的時間而不是一年中的實際日期感興趣。 如何從POSIXct
類向量中提取時間為小時:秒?
這是一個很好的問題,並強調了處理R中日期的一些困難。潤滑包非常方便,所以下面我介紹兩種方法,一種使用鹼(如@ RJ-所示),另一種使用lubridate。
重新創建原始帖子中數據框的(前兩行):
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類(兩種方法)
# 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)
現在,提取時間為十進制小時
# 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")
你可以依賴基數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)))
並且plot
和ggplot2
知道如何在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)
此代碼比轉換為字符串並返回數字要快得多
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
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以與其名稱所建議的相反的順序獲取參數(這樣只需要幾秒鍾)
這是一個古老的話題,但我發現這個問題很少有問題和答案。 我的解決方案如下
library(hms)
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))
foo$start.time = as.POSIXct( foo$start.time )
g1 = ggplot( ) + xlab("") +
geom_line( data = foo, aes(x = as.hms(start.time), y = duration ), color = "steelblue" )
g1
如果你想添加手動時間(!)休息,那么
time_breaks = as.POSIXlt(c(
"2012-02-06 12:35:00 MSK",
"2012-02-06 13:15:00 MSK",
"2012-02-06 14:22:00 MSK",
"2012-02-06 15:22:00 MSK"))
g1 +
scale_x_time( breaks = as.hms( time_breaks ) ) +
theme( axis.text.x = element_text( angle=45, vjust=0.25) )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.