Преобразование символьного вектора во время и извлечение значений

#r #date #dplyr #lubridate

#r #Дата #dplyr #lubridate

Вопрос:

Привет, у меня возникли некоторые проблемы с объектами даты и времени в R. У меня есть столбец, который на самом деле является просто столбцом времени, но когда он вводится в R, он считывается как вектор символов, но также со случайной датой. Моя первоначальная мысль, связанная с этой проблемой, заключалась в том, чтобы сначала преобразовать этот столбец time в объект datetime, используя lubridate::mdy_hms() , а затем извлекая только время, используя strftime() или srtptime() , но, насколько я понимаю, это strptime() применимо только к символьным векторам, тогда strftime() как применяется к значениям POSIXct. Я использую mdy_hms() функцию для преобразования поля в объект POSIXct, а затем пытаюсь извлечь только время использования strftime() , но на самом деле это не работает. Я получаю эту ошибку:

 Error in as.POSIXlt.default(x, tz = tz) : 
  do not know how to convert 'x' to class “POSIXlt”
 

Я попробовал это снова, но с помощью hms пакета, однако он не распознает полные значения в моем векторе времени и преобразует все в NA значения. Вот почему я подумал сначала преобразовать все значения в этом символьном векторе в значения даты и времени, а затем «выбросить» значение даты, поскольку оно неверно. Это код, который я пытаюсь запустить:

 library(tidyverse)
library(lubridate)
library(hms)

OM <- read_csv('OM_sightings-1948-2019.csv', na = c("", "NA", "<Null>")) %>%
    #Rename the ID column to OM_ID --> indicates that this entry came from OM database
    rename(OM_ID = ID, Time = Time1, OM_Source = Source) %>% 
    # Drop the Time2, column
    select(-Time2) %>% 
    # Convert 0.0 to NA in both the ActLat and ActLong columns
    mutate_at(vars(ActLat, ActLong), na_if, y = 0)

#Fix the date and time objects in the db
OM_time <- OM %>% 
    mutate(Time = as_hms(Time),
           SightDate = as.Date(mdy_hms(SightDate), tz = "US/Pacific"),
           SightDateTime = mdy_hms(paste(SightDate, Time1), tz = "US/Pacific"))
 

Он работает нормально, и я вижу свой «мутированный» df, однако я получаю эти предупреждающие сообщения, которые я понимаю (в основном), но не уверен, как устранить неполадки:

 Warning messages:
1: Problem with `mutate()` input `Time`.
ℹ Lossy cast from <character> to <hms> at position(s) 58, 60, 61, 62, 63, ... (and 102131 more)
ℹ Input `Time` is `as_hms(Time)`. 
2: Lossy cast from <character> to <hms> at position(s) 58, 60, 61, 62, 63, ... (and 102131 more) 
3: Problem with `mutate()` input `SightDateTime`.
ℹ All formats failed to parse. No formats found.
ℹ Input `SightDateTime` is `mdy_hm(SightDate, tz = "US/Pacific")   Time`. 
4: All formats failed to parse. No formats found. 
 

Это примерное подмножество моих данных:

 structure(list(OM_ID = c(94079, 75473, 95592, 50725, 24689, 73538, 
10246, 107438, 10129, 74301, 107371, 63757, 43427, 93087, 16374, 
28869, 38644, 42348, 89933, 83809, 53855, 96622, 52702, 28263, 
991), SightDate = c("4/22/2015 0:00:00", "7/15/2011 0:00:00", 
"6/30/2015 0:00:00", "6/26/2007 0:00:00", "8/12/2000 0:00:00", 
"6/11/2011 0:00:00", "6/28/1990 0:00:00", "12/7/2018 0:00:00", 
"6/20/1990 0:00:00", "6/26/2011 0:00:00", "12/5/2018 0:00:00", 
"9/1/2009 0:00:00", "8/27/2005 0:00:00", "11/14/2014 0:00:00", 
"6/11/1997 0:00:00", "9/10/2001 0:00:00", "9/8/2004 0:00:00", 
"7/18/2005 0:00:00", "6/25/2014 0:00:00", "8/6/2012 0:00:00", 
"5/16/2008 0:00:00", "7/25/2015 0:00:00", "9/10/2007 0:00:00", 
"8/16/2001 0:00:00", "1/6/1977 0:00:00"), Time = c("12/30/1899 14:00:00", 
"12/30/1899 15:00:00", "12/30/1899 19:21:00", "12/30/1899 9:30:00", 
"12/30/1899 9:30:00", "12/30/1899 12:00:00", "12/30/1899 18:30:00", 
"12/30/1899 13:00:00", "12/30/1899 18:00:00", "12/30/1899 11:52:00", 
"12/30/1899 9:15:00", "12/30/1899 15:33:00", "12/30/1899 9:00:00", 
"12/30/1899 13:48:00", "12/30/1899 15:00:00", "12/30/1899 5:45:00", 
NA, "12/30/1899 16:15:00", "12/30/1899 12:30:00", NA, "12/30/1899 12:00:00", 
"12/30/1899 13:00:00", "12/30/1899 12:30:00", "12/30/1899 8:45:00", 
"12/30/1899 14:15:00"), Month = c(4, 7, 6, 6, 8, 6, 6, 12, 6, 
6, 12, 9, 8, 11, 6, 9, 9, 7, 6, 8, 5, 7, 9, 8, 1), Day = c(22, 
15, 30, 26, 12, 11, 28, 7, 20, 26, 5, 1, 27, 14, 11, 10, 8, 18, 
25, 6, 16, 25, 10, 16, 6), Year = c(2015, 2011, 2015, 2007, 2000, 
2011, 1990, 2018, 1990, 2011, 2018, 2009, 2005, 2014, 1997, 2001, 
2004, 2005, 2014, 2012, 2008, 2015, 2007, 2001, 1977), Pod = c("Orcas", 
"JpLp", "JK", "Orcas", "L", "J", "Orcas", "J", "J", "JK", "J", 
"L12s", "Orcas", "J", "Orcas", "Orcas", "JKL", "J", "J", "J", 
"J", "JKL", "JL", "JL", "Orcas"), LikelyPod = c("Ts", "JKLp", 
"JpKp", NA, NA, "JL53", NA, NA, NA, "JpKp", NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, "SRs"), Direction = c(NA, 
"mill", NA, NA, "E", "SE", "N", "N", "W", NA, "N", "NW", "N", 
NA, "N", NA, "N", "N", "N", "N", "N", "SW", NA, "N", "N"), FishArea = c("17C", 
"7", "7", "7", "19C", "7", "7", "9", "18C", "18C", "11", "7", 
"7", "9", "7", "7", "7", "18C", "7", "7", "18C", "18", "29", 
"7", "10"), Quadrant = c(89, 184, 181, 184, 257, 181, 185, 397, 
151, 152, 420, 185, 181, 387, 169, 181, 181, 162, 176, 170, 163, 
151, 80, 176, 413), Lat = c(48.96, 48.46, 48.5, 48.46, 48.31, 
48.5, 48.44, 47.9, 48.76, 48.74, 47.33, 48.44, 48.5, 48.12, 48.62, 
48.5, 48.5, 48.74, 48.56, 48.65, 48.71, 48.76, 49.01, 48.56, 
47.55), Long = c(-123.73, -123.1, -123.17, -123.1, -123.36, -123.17, 
-123.03, -122.46, -123.02, -123.08, -122.44, -123.03, -123.17, 
-122.71, -123.17, -123.17, -123.17, -123.3, -123.21, -123.24, 
-123.26, -123.02, -123.16, -123.21, -122.41), UTMx = c(446800, 
492000, 487000, 492000, 473400, 487000, 497400, 539100, 497800, 
493500, 540300, 497400, 487000, 520500, 486900, 487000, 487000, 
477600, 484200, 482300, 480700, 497800, 488100, 484200, 542200
), UTMy = c(5423900, 5367800, 5372600, 5367800, 5351700, 5372600, 
5365800, 5305200, 5401200, 5399200, 5242800, 5365800, 5372600, 
5329700, 5386000, 5372600, 5372600, 5399000, 5378600, 5389300, 
5395300, 5401200, 5428700, 5378600, 5266600), OM_Source = c("TWM-SA-Pub", 
"TWM-SW", "TWM-HYD-Rel", "TWM-Pager", "TWM-Pager", "TWM-SW", 
"TWM-SA-Rel", "TWM-SA-Rel", "TWM-SA-Rel", "SPOT", "TWM-SA-Pub", 
"SPOT", "TWM-Pager", "TWM-HYD-Rel", "TWM-Pager", "TWM-SA-Pub", 
"TWM-SA-Rel", "TWM-Pager", "TWM-SW", "BCCSN", "TWM-SW", "Soundwatch", 
"BCCSN", "TWM-Pager", "TWM-SA-Rel"), ActLat = c(NA, 48.452, NA, 
NA, NA, 48.488, NA, NA, NA, 48.7667, NA, 48.4585, NA, NA, NA, 
NA, NA, NA, 48.5385, 48.682, 48.738, 48.7876, 49.0108, NA, NA
), ActLong = c(NA, -123.0777, NA, NA, NA, -123.1233, NA, NA, 
NA, -123.0776, NA, -123.065, NA, NA, NA, NA, NA, NA, -123.1725, 
-123.251, -123.253, -123.0389, -123.1659, NA, NA)), row.names = c(NA, 
-25L), class = c("tbl_df", "tbl", "data.frame"))
 

Я ценю любую помощь! Я довольно новичок / самоучка, и мне трудно понять, как лучше всего работать с данными о времени в целом.

Комментарии:

1. Это сводится к тому, что представляют времена. Если это времена суток, вам лучше всего сохранить их как даты и времени и печатать только временную часть. Если это длительности, вы можете либо сохранить их как целые числа секунд или минут, либо использовать что-то вроде duration from lubridate .

2. Вы поделились своими данными после некоторой обработки, которую вы обсуждали, и со столбцом «tz». Возможно, было бы более полезно опубликовать примерные данные с более раннего этапа процесса, прежде чем вообще преобразовывать время.

3. Извините, я этого не понял! Я только что обновил dput() свое подмножество. Пожалуйста, дайте мне знать, если это работает нормально!

4. @AllanCameron извините за неясность, я пытаюсь сохранить эти данные как объект времени суток. Не длительность. Честно говоря, я действительно раздражен тем, как были импортированы эти данные, потому что в исходной базе данных в столбце time нет даты, и я думаю, что это искусственный экспорт и импорт на разных платформах.

Ответ №1:

Даты и время могут быть довольно сложными в R, поскольку существует так много разных способов их представления. lubridate не имеет класса, который является просто time, но связанный пакет hms добавляет класс time, который может упростить задачу.

Я часто считаю полезным иметь столбцы даты и даты / времени, чтобы вы могли использовать ту часть, которая имеет наибольший смысл.
Для примера данных, используя lubridate::mdy_hms(SighDate), он преобразуется в дату в полночь. hms::as_hms(Time) сработало для меня. Затем добавьте два для создания в столбце date_time, затем преобразуйте дату в класс date, если вам это нужно для анализа. Ниже я создал новый столбец для time, чтобы отслеживать, что он делает, но, как правило, заменяет столбец time.

 library(lubridate)
library(hms)
library(tidyverse)
# OM = your data provided above 

OM2 <- OM %>%
      mutate(SightDate = mdy_hms(SightDate, tz = "America/Los_Angeles"),
             Time2 = as_hms(mdy_hms(Time)),
             Date_time = SightDate Time2,
             SightDate = as.Date(SightDate)
             )

OM2 %>%
      select(OM_ID, SightDate, Time, Time2, Date_time, everything())

# # A tibble: 25 x 20
# OM_ID SightDate  Time  Time2 Date_time           Month   Day  Year Pod   LikelyPod Direction FishArea Quadrant   Lat
# <dbl> <date>     <chr> <tim> <dttm>              <dbl> <dbl> <dbl> <chr> <chr>     <chr>     <chr>       <dbl> <dbl>
#       1  94079 2015-04-22 12/3~ 14:00 2015-04-22 14:00:00     4    22  2015 Orcas Ts        NA        17C            89  49.0
# 2  75473 2011-07-15 12/3~ 15:00 2011-07-15 15:00:00     7    15  2011 JpLp  JKLp      mill      7             184  48.5
# 3  95592 2015-06-30 12/3~ 19:21 2015-06-30 19:21:00     6    30  2015 JK    JpKp      NA        7             181  48.5
# 4  50725 2007-06-26 12/3~ 09:30 2007-06-26 09:30:00     6    26  2007 Orcas NA        NA        7             184  48.5
# 5  24689 2000-08-12 12/3~ 09:30 2000-08-12 09:30:00     8    12  2000 L     NA        E         19C           257  48.3
# 6  73538 2011-06-11 12/3~ 12:00 2011-06-11 12:00:00     6    11  2011 J     JL53      SE        7             181  48.5
# 7  10246 1990-06-28 12/3~ 18:30 1990-06-28 18:30:00     6    28  1990 Orcas NA        N         7             185  48.4
# 8 107438 2018-12-07 12/3~ 13:00 2018-12-07 13:00:00    12     7  2018 J     NA        N         9             397  47.9
# 9  10129 1990-06-20 12/3~ 18:00 1990-06-20 18:00:00     6    20  1990 J     NA        W         18C           151  48.8
# 10  74301 2011-06-26 12/3~ 11:52 2011-06-26 11:52:00     6    26  2011 JK    JpKp      NA        18C           152  48.7
# # ... with 15 more rows, and 6 more variables: Long <dbl>, UTMx <dbl>, UTMy <dbl>, OM_Source <chr>, ActLat <dbl>,
# #   ActLong <dbl>

 

Я почти уверен, что Access представляет даты и время в виде числовых значений, представляющих количество времени с момента некоторого происхождения. Похоже, что используется исходное значение 12/30/1899, которое отображается в вашем столбце времени. Вы также можете просмотреть свои настройки при экспорте из Access в csv. Я больше знаком с Excel, но думаю, что они настроили его аналогично, чтобы вы могли манипулировать форматом перед импортом.

Комментарии:

1. Спасибо! Так что да, я не хотел давать слишком много подробностей, опасаясь запутать мой пост, но да. У меня есть столбец даты с истинной датой, а столбец времени (в Access) отображает время только в 24-часовом формате. Однако при импорте в R он добавляет случайную дату. Использование hms::as_hms вызова делает то, чего я боялся, и удаляет все содержимое вектора времени и вместо этого заполняет его значениями NA. Я обновлю свой OP, чтобы отразить лучший вопрос, код и образцы данных. Большое спасибо за вашу помощь!

2. Я обновил новые данные образца. Использование предоставленного вами примера as_hms работало нормально, но если он возвращает NA, это может быть вызвано чем-то за пределами опубликованного вами подмножества.

3. Я думаю, что ваши ошибки возникают из-за использования as_hms для данных, которые имеют компонент даты, а также компонент времени. Вы можете либо сначала преобразовать в POSIXct с помощью mdy_hms(), либо удалить бессмысленный компонент даты перед преобразованием символа во время.

4. Да! Это сработало, спасибо! Однако, когда у меня есть NA значения времени, они по-прежнему заполняются в столбце SightDateTime, т.е. (1/1/2010 NA), но я надеялся, что если для time было NA, оно не будет добавлено к SightDateTime. Я также по-прежнему получаю столбец «tz», добавленный в конец моего df, тогда как в прошлом этого не происходило, и я не уверен, почему? Это код, который я в итоге запустил: OM_time <- OM %>% mutate(Time = as_hms(mdy_hms(Time)), SightDate = as.Date(mdy_hms(SightDate), tz = "US/Pacific"), SightDateTime = paste(SightDate, Time), tz = "US/Pacific")

5. Вы создаете столбец tz в приведенном выше коде, я думаю, он должен быть внутри круглых скобок для mdy_hms.