2016-09-30 4 views
0

У меня есть некоторые числовые данные о дате из Excel:Работа с числовыми (десятичными) датами в R?

> df <- data.frame(c(42613, 42612, 42614), c(42614.61, 42613.97, 42612.12)) 
> names(df) <- c("Closetime", "Opentime") 

Оба Closetime и Opentime являются numeric. Я хочу сохранить час/минута/секунда данные из OpenTime и добавить время '00: 00: 00' на каждый день в Closetime:

> df$Closetime <- paste(as.Date(df$Closetime, origin = '1900-01-01'), c('00:00:00')) 

Easy достаточно, чтобы сделать Closetime, но когда я пытаюсь использовать lubridate::date_decimal на Opentime, все идет к черту.

> df$Opentime <- date_decimal(df$Opentime) 
> df 
      Closetime    Opentime 
1 2016-09-02 00:00:00 42614-08-11 15:36:00 
2 2016-09-01 00:00:00 42613-12-21 01:12:00 
3 2016-09-03 00:00:00 42612-02-13 22:04:48 

Как я могу получить как Opentime и Closetime быть одного и того же типа/формата? В конце концов, я ищу, чтобы иметь возможность получить разницу в часах между временами в каждом столбце для справки.

ответ

2

Если вы можете использовать POSIXct, вы можете сделать, например

df$Opentime <- as.POSIXct(df$Opentime*24*60*60, 
       origin="1900-01-01", 
       tz="UTC") 

Рассуждение: POSIXct только количество секунд, прошедших с происхождения

+2

Ну, это самый худший способ масштабирования дней в секундах, как ваш * свободный *, например, пара секунд регулировки. Другие ответы показывают, как сделать это правильно, используя типы R. –

+0

@DirkEddelbuettel справедливая точка, но, возможно, если вы делаете все промежуточные преобразования, вы должны указать, какая цель служит. –

+0

Приходите еще? Обращайтесь к моему ответу ниже? Можешь прочитать? –

2

Сначала мы следуем совету в help("as.Date") о датах Excel. Я предполагаю, что здесь для Windows Excel:

df$Closetime_p <- as.Date(df$Closetime, origin = "1899-12-30") 
df$Opentime_p <- as.Date(floor(df$Opentime), origin = "1899-12-30") 

Затем мы преобразуем в POSIXct:

df$Closetime_p <- as.POSIXct(as.POSIXlt(df$Closetime_p, tz = "GMT"), tz = "GMT") 
df$Opentime_p <- as.POSIXct(as.POSIXlt(df$Opentime_p, tz = "GMT"), tz = "GMT") 

Теперь мы добавим время:

df$Opentime_p <- df$Opentime_p + (df$Opentime - floor(df$Opentime)) * 24 * 3600 
# Closetime Opentime Closetime_p   Opentime_p 
#1  42613 42614.61 2016-08-31 2016-09-01 14:38:24 
#2  42612 42613.97 2016-08-30 2016-08-31 23:16:48 
#3  42614 42612.12 2016-09-01 2016-08-30 02:52:48 
1

Преобразовать на сегодняшний день, как вы, а затем преобразовать в POSIXct :

Сначала создайте data.frame (и обратите внимание, как мы задаем имена столбцов):

R> df <- data.frame(CloseT=c(42613, 42612, 42614), OpenT=c(42614.61, 42613.97, 42612.12)) 
R> df 
    CloseT OpenT 
1 42613 42614.6 
2 42612 42614.0 
3 42614 42612.1 
R> 

Затем преобразовать Дата:

R> df$CloseT <- as.Date(df$CloseT, origin="1900-01-01") 
R> df$OpenT <- as.Date(df$OpenT, origin="1900-01-01") 
R> df 
     CloseT  OpenT 
1 2016-09-02 2016-09-03 
2 2016-09-01 2016-09-02 
3 2016-09-03 2016-09-01 
R> 

Наконец, конвертировать в POSIXct:

R> df$OpenT <- as.POSIXct(df$OpenT) 
R> df$CloseT <- as.POSIXct(df$CloseT) 
R> df 
       CloseT    OpenT 
1 2016-09-01 19:00:00 2016-09-03 09:38:24 
2 2016-08-31 19:00:00 2016-09-02 18:16:48 
3 2016-09-02 19:00:00 2016-08-31 21:52:48 
R> 

Переход через POSIXlt позволяет установить часовой пояс, как показал Roland.

1

Проверьте документацию на date_decimal:

объект POSIXct, чей год соответствует целой части десятичной.

date <- ymd("2009-02-10") 
decimal <- decimal_date(date) # 2009.11 
date_decimal(decimal) # "2009-02-10 UTC" 

Таким образом, в вашем примере, это интерпретация 42614 в год.

Попробуйте использовать as.POSIXct. Возможно, вам придется указать часовой пояс, но если вам нужно только дельта, это не понадобится.Ниже я рассчитывается разницу во времени:

df <- data.frame(c(42613, 42612, 42614), c(42614.61, 42613.97, 42612.12)) 
names(df) <- c("Closetime", "Opentime") 
df$Closetime <- as.POSIXct(as.Date(df$Closetime, origin = '1900-01-01')) 
df$Opentime <- as.POSIXct(as.Date(df$Opentime, origin = '1900-01-01')) 
df$delta <- df$Opentime - df$Closetime 
df 
      Closetime   Opentime  delta 
1 2016-09-01 20:00:00 2016-09-03 10:38:24 1.61 days 
2 2016-08-31 20:00:00 2016-09-02 19:16:48 1.97 days 
3 2016-09-02 20:00:00 2016-08-31 22:52:48 -1.88 days 

Основываясь на комментарий, если вы хотите, чтобы убедиться, что дисплей имеет правильный час, вы должны правильно соответствовать часовых поясов. Вы можете сделать это после преобразования в as.POSIXct, установив атрибут tzone.

df <- data.frame(c(42613, 42612, 42614), c(42614.61, 42613.97, 42612.12)) 
names(df) <- c("Closetime", "Opentime") 
df$Closetime <- as.POSIXct(as.Date(df$Closetime, origin = '1900-01-01')) 
df$Opentime <- as.POSIXct(as.Date(df$Opentime, origin = '1900-01-01')) 
attr(df$Closetime, "tzone") <- "GMT" 
attr(df$Opentime, "tzone") <- "GMT" 
df$delta <- df$Opentime - df$Closetime 
df 

    Closetime   Opentime  delta 
1 2016-09-02 2016-09-03 14:38:24 1.61 days 
2 2016-09-01 2016-09-02 23:16:48 1.97 days 
3 2016-09-03 2016-09-01 02:52:48 -1.88 days 
+0

Если бы я хотел, чтобы «Closetime» получало время «00: 00: 00» для всех значений, как бы я это сделал? Есть ли параметр, который мне нужно указать? – blacksite

+0

Ничего, я смог выполнить это с помощью 'lubridate :: hour' и установки' hour (df $ Closetime) <- 0'. – blacksite

+2

, если ваша цель - рассчитать разницу между двумя, это может сбросить ваши расчеты. Я отредактирую, чтобы показать, как вы можете заставить его по часовой стрелке GMT, чтобы «Closetime» оставался без часа. –

Смежные вопросы