#r #dplyr #data.table
#r #dplyr #данные.таблица
Вопрос:
Для данных ниже:
> dt
date event1 event2 event3
1: 2016-04-27 10:25:15 11:05:45 13:00:09
2: 2016-04-27 10:25:15 11:05:45 13:00:09
3: 2016-04-27 10:25:15 11:05:45 13:00:09
4: 2016-04-27 10:25:15 11:05:45 13:00:09
5: 2016-04-27 10:25:15 11:05:45 13:00:09
Я хотел бы объединить date
с каждым из столбцов событий, чтобы преобразовать столбцы времени события в datetime
формат. Желаемый результат:
dt$event1 = as.POSIXct(paste(dt$date, dt$event1), format="%Y-%m-%d %H:%M:%S")
dt$event2 = as.POSIXct(paste(dt$date, dt$event2), format="%Y-%m-%d %H:%M:%S")
dt$event3 = as.POSIXct(paste(dt$date, dt$event3), format="%Y-%m-%d %H:%M:%S")
dt$date = NULL
> dt
event1 event2 event3
1: 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
2: 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
3: 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
4: 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
5: 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
Поскольку у меня довольно большой набор данных с >300 тыс. строк и> 20 столбцами времени события, какой наиболее эффективный способ сделать это сразу для всех столбцов времени события в dplyr
или data.table
, пожалуйста?
Пример данных:
dt = data.table(date = rep(as.POSIXct("2016-04-27"),5), event1 = rep("10:25:15",5), event2 = rep("11:05:45",5), event3 = rep("13:00:09",5))
Комментарии:
1. Не могли бы вы, пожалуйста, предоставить желаемый результат?
2. Я не слишком обеспокоен дублированием. В примере
event1
можно было бы просто заменить вместо генерацииevent1_datetime
— обновит вопрос, чтобы сделать его более понятным
Ответ №1:
Не уверен, какое это имеет отношение к слиянию; разве это не просто
dt[, event1_datetime := as.POSIXct(paste(date, event1))]
# date event1 event2 event3 event1_datetime
#1: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#2: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#3: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#4: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#5: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
Обновить
Как бы то ни было, вот data.table
решение, использующее melt
и dcast
dt[, n := 1:.N]
dt <- melt(dt[, n := 1:.N], id.vars = c("date", "n"), value.name = "time")
dt[, datetime := as.POSIXct(paste(date, time))]
dt <- dcast(dt, date n ~ variable, value.var = c("time", "datetime"))
dt[, n := NULL]
# date time_event1 time_event2 time_event3 datetime_event1
#1: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#2: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#3: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#4: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
#5: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15
# datetime_event2 datetime_event3
#1: 2016-04-27 11:05:45 2016-04-27 13:00:09
#2: 2016-04-27 11:05:45 2016-04-27 13:00:09
#3: 2016-04-27 11:05:45 2016-04-27 13:00:09
#4: 2016-04-27 11:05:45 2016-04-27 13:00:09
#5: 2016-04-27 11:05:45 2016-04-27 13:00:09
Или все за один раз
dcast(melt(dt[, n := 1:.N], id.vars = c("date", "n"), value.name = "time")[,
datetime := as.POSIXct(paste(date, time))],
date n ~ variable, value.var = c("time", "datetime"))[,
n := NULL][]
Комментарии:
1. да, но я хотел бы сделать это для всех столбцов событий (
event1
,event2
event3
и т.д., Всех сразу.2. Ах, я понимаю; хорошо, в этом случае изменение формы с wide на long, затем добавление даты и изменение формы обратно на wide будет работать. Я опубликую обновление…
3. @pyne Чего бы это (все еще) ни стоило, я добавил
data.table
решение, которое учитывает произвольное количество столбцов событий.4. Спасибо, @Maurits Evers — Я обычно считаю
data.table
, что это быстрее, так здорово иметь такую возможность!
Ответ №2:
Мы можем использовать mutate_at
для добавления новых столбцов
library(dplyr)
dt %>%
mutate_at(vars(starts_with("event")), funs(as.POSIXct(paste0(date, .)))) %>%
select(-date)
# event1 event2 event3
#1 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
#2 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
#3 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
#4 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
#5 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
Комментарии:
1. Спасибо! и спасибо за обновление вашего ответа после того, как мой вопрос был отредактирован — действительно ценю это!
Ответ №3:
Возможный подход с использованием .SDcols
:
cols <- paste0(grep("^event", names(dt), value=TRUE), "_datetime")
dt[, (cols) :=
lapply(.SD, function(x) as.POSIXct(paste(date, x), format="%Y-%m-%d %H:%M:%S")),
.SDcols=event1:event3]
вывод:
date event1 event2 event3 event1_datetime event2_datetime event3_datetime
1: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
2: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
3: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
4: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
5: 2016-04-27 10:25:15 11:05:45 13:00:09 2016-04-27 10:25:15 2016-04-27 11:05:45 2016-04-27 13:00:09
данные:
library(data.table)
dt <- fread("date event1 event2 event3
2016-04-27 10:25:15 11:05:45 13:00:09
2016-04-27 10:25:15 11:05:45 13:00:09
2016-04-27 10:25:15 11:05:45 13:00:09
2016-04-27 10:25:15 11:05:45 13:00:09
2016-04-27 10:25:15 11:05:45 13:00:09")