Вопрос по r, ggplot2 – извлекать часы и секунды из POSIXct для построения графиков в R

52

Предположим, у меня есть следующее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 класс вектора?

Благодарю. Одна проблема сformat(foo$start.time, format='%H:M') является то, что вывод в символьном формате. Мне бы хотелось, чтобы выходные данные были в каком-то числовом формате, чтобы его можно было использовать в качестве оси x графика. andrewj
Хорошо, используяlubridate пакет, я могу сделатьx <- hour(foo$start.time) + minute(foo$start.time)/60 что составляет 90% от того, что я ищу. Тем не менее, когда яplot xЯ хотел бы иметь возможность отформатировать его в часах: минутах. Есть дополнительные мысли? andrewj
зависит от того, как вы планируете, но пост, на который я ссылался, должен помочь. Justin
Есть много способов. Снова я хочу указать вамlubridate или жеthis post Justin
библиотекиlubridate а такжеzoo может быть полезным для вас. но в базе R,format(foo$start.time, format='%H:M'). Justin

Ваш Ответ

4   ответа
7

чем преобразование в строку и обратно в число

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
6

поэтому Хэдли рекомендует пакет 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 принимает аргументы в порядке, противоположном тому, который предлагается его именем (так что могут быть предоставлены только секунды)

46

и он подчеркивает некоторые трудности в работе с датами в R. Пакет lubridate очень удобен, поэтому ниже я представляю два подхода, один из которых использует base (как предложено @ 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")
Error: User Rate Limit ExceededlubridateError: User Rate Limit Exceededstrptime
Error: User Rate Limit ExceededfooError: User Rate Limit Exceededfoo$start.time.numeric <- hour(foo$start.time) + minute(foo$start.time)/60Error: User Rate Limit Exceededwith(foo, qplot(start.time.numeric, duration)) andrewj
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/questions/7655514/…Error: User Rate Limit Exceededqplot(hour(foo$start.time) + minute(foo$start.time)/60, foo$duration) + scale_x_datetime(labels = date_format("%S:00"))Error: User Rate Limit Exceededscale_x_datetimeError: User Rate Limit ExceededlabelsError: User Rate Limit Exceeded andrewj
Error: User Rate Limit Exceededlubridate::ymd_hmsError: User Rate Limit Exceededlubridate::hourError: User Rate Limit Exceededlubridate::minuteError: User Rate Limit Exceededas.numeric(format(foo$start.time), "%H")Error: User Rate Limit Exceededas.numeric(format(foo$start.time), "%M")Error: User Rate Limit Exceeded
17

# 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 года, но если вы не указали дату и вместо этого используете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)

Похожие вопросы