Как я могу преобразовать конкретное время в

Я хочу преобразовать строковый столбец в правильный формат.

Обычно я бы сделал что-то вроде:

print(df$Time) 
> "00:00:01"
as.POSIXct(df$Time,format="%H:%M:%S")

Однако мои данные странные. Это выглядит так:

print(df$Time)
850a"  "823a"  NA      "906a"  "321a"  "1154p"

Мое решение не работает. Так как я сначала разделил символы (в данном случае «а» и «р»). Но после этого в моем времени отсутствует важная часть (будь то утро или день).

Поэтому мой вопрос: как я могу преобразовать эти данные в правильный формат?

Ожидаемый результат:

df$Time_Old
850a"  "823a"  NA      "906a"  "321a"  "1154p"

df$Time_New
08.50   08.23    NA    09.06   03.21   23.54

Некоторые примеры данных:

vector_string <- as.vector(tv_Adds[["Time"]])
vector_string = vector_string[1:20]
> vector_string 


[1] "850a"  "823a"  NA      "906a"  "321a"  "1154p" "608p"  "1012a" "354a"  "1121p" "414p"  "1241p" "721p"  "223p"  "316p" 
[16] "345p"  "1145a" "3p"    "937a"  "138p"

> dput(vector_string[1:20])
c("850a", "823a", NA, "906a", "321a", "1154p", "608p", "1012a", 
"354a", "1121p", "414p", "1241p", "721p", "223p", "316p", "345p", 
"1145a", "3p", "937a", "138p")

person R overflow    schedule 25.10.2019    source источник
comment
Не могли бы вы поделиться более воспроизводимым примером? Возможно, образец ваших данных, текущий и ожидаемый результат? Ваш вопрос немного неясен, по крайней мере для меня.   -  person NelsonGon    schedule 25.10.2019
comment
О, так а и р — это am и pm?   -  person Sotos    schedule 25.10.2019
comment
Привет, @Sotos, действительно, a и p a am и pm (да .. это действительно грязно)   -  person R overflow    schedule 29.10.2019
comment
@NelsonGon конечно, я добавил образец своих данных. Заранее спасибо!   -  person R overflow    schedule 29.10.2019
comment
Не могли бы вы сделать dput(vector_string[1:20]) и опубликовать свои примеры данных, чтобы их можно было воспроизвести?   -  person Sotos    schedule 29.10.2019
comment
Конечно @Sotos. Сделанный!   -  person R overflow    schedule 29.10.2019


Ответы (2)


Основываясь на вашем общем примере, кажется, что у вас есть 3 разных случая, которые нам нужно обработать.

  1. Когда у вас есть 834a, который должен стать 8:34am
  2. Когда у вас есть 1143p, который должен стать 11:43pm
  3. Когда у вас есть 3a, который должен стать 3:00am

Как только они будут обработаны, в данном случае с помощью простого оператора ifelse, подсчитывающего количество символов и соответствующим образом модифицирующего, мы можем просто преобразовать объект datetime, вызвав strptime с правильным форматом, т.е.

v1[!is.na(v1)] <- paste0(v1[!is.na(v1)], 'm')
v2 <- ifelse(nchar(v1) == 5, gsub('(^[0-9]{1})(.*$)', '\\1:\\2', v1), 
           ifelse(nchar(v1) == 3, gsub('(^[0-9]{1})(.*$)', '\\1:00\\2', v1), 
                                                  gsub('(^[0-9]{2})(.*$)', '\\1:\\2', v1)))

v2
#[1] "8:50am"  "8:23am"  NA        "9:06am"  "3:21am"  "11:54pm" "6:08pm"  "10:12am" "3:54am"  "11:21pm" "4:14pm"  "12:41pm" "7:21pm"  "2:23pm"  "3:16pm"  "3:45pm"  "11:45am" "3:00pm"  "9:37am"  "1:38pm" 

strptime(v2, format = '%I:%M%p')
#[1] "2019-10-29 08:50:00 +03" "2019-10-29 08:23:00 +03" NA                        "2019-10-29 09:06:00 +03" "2019-10-29 03:21:00 +03" "2019-10-29 23:54:00 +03" "2019-10-29 18:08:00 +03" "2019-10-29 10:12:00 +03" "2019-10-29 03:54:00 +03" "2019-10-29 23:21:00 +03"
#[11] "2019-10-29 16:14:00 +03" "2019-10-29 12:41:00 +03" "2019-10-29 19:21:00 +03" "2019-10-29 14:23:00 +03" "2019-10-29 15:16:00 +03" "2019-10-29 15:45:00 +03" "2019-10-29 11:45:00 +03" "2019-10-29 15:00:00 +03" "2019-10-29 09:37:00 +03" "2019-10-29 13:38:00 +03"

ИСПОЛЬЗУЕМЫЕ ДАННЫЕ

dput(v1)
c("850am", "823am", NA, "906am", "321am", "1154pm", "608pm", 
"1012am", "354am", "1121pm", "414pm", "1241pm", "721pm", "223pm", 
"316pm", "345pm", "1145am", "3pm", "937am", "138pm")
person Sotos    schedule 29.10.2019
comment
Ваше решение работает! Однако, если вы используете предоставленные данные, вы должны добавить (перед своим решением): v1 ‹- tolower(v1) v1 ‹- gsub(a,am, v1) v1 ‹- gsub(p,pm,v1) - person R overflow; 29.10.2019
comment
О, я забыл добавить этот шаг: P... добавил его сейчас. Вы можете использовать пасту и не делать 2 gsub - person Sotos; 29.10.2019

Вы должны отделить часы от минут, поскольку ввод, который вы даете, неоднозначен. Затем добавьте «m» в конце записей, не относящихся к Северной Америке. Я думаю, вам нужно это:

tvec = c("850a",  "823a",  NA, "906a",  "321a",  "1154p")
notNA <- !is.na(tvec)

#separate hours from minutes with a dot and append m at the end:
tvec[notNA] <- paste0(strtrim(tvec[notNA], nchar(tvec[notNA]) - 3), ".", 
                      substr(tvec[notNA], nchar(tvec[notNA])-2, nchar(tvec[notNA]))
, "m")

as.POSIXct(tvec, format = "%I.%M%p")
[1] "2019-10-25 08:50:00 CEST" "2019-10-25 08:23:00 CEST"
[3] NA                         "2019-10-25 09:06:00 CEST"
[5] "2019-10-25 03:21:00 CEST" "2019-10-25 23:54:00 CEST"

"%I.%M%p" означает

hour(0-12), followed by .,followed by minutes(00-59), followed by "am"(or "pm")

person Grada Gukovic    schedule 25.10.2019
comment
Спасибо @Grada! Я использовал ваш код, но получил сообщение об ошибке: Ошибка в strtrim(tvec[notNA], nchar(tvec[notNA]) - 3): неверный аргумент 'width' - person R overflow; 29.10.2019
comment
Я добавил пример данных, который я использовал для тестирования... Еще раз большое спасибо! - person R overflow; 29.10.2019