#r
#r
Вопрос:
Время (фрейм данных):
CentralTime Batch Id
2020-04-01 03:46:01 UTC
2020-04-01 10:46:01 UTC
2020-04-01 10:54:18 UTC
2020-04-01 10:54:25 UTC
2020-04-01 10:54:31 UTC
2020-04-01 10:55:06 UTC
2020-04-01 10:55:12 UTC
2020-04-01 10:55:26 UTC
2020-04-01 10:55:32 UTC
2020-04-01 10:55:39 UTC
2020-04-01 10:55:45 UTC
2020-04-01 10:56:20 UTC
2020-04-01 10:56:26 UTC
2020-04-01 10:56:33 UTC
2020-04-01 10:56:39 UTC
2020-04-01 10:56:53 UTC
2020-04-01 10:56:59 UTC
2020-04-01 10:57:06 UTC
2020-04-01 10:57:14 UTC
2020-04-01 10:57:20 UTC
2020-04-01 11:37:20 UTC
2020-04-01 11:38:27 UTC
2020-04-01 11:38:33 UTC
2020-04-01 11:38:47 UTC
2020-04-01 11:38:53 UTC
2020-04-01 11:39:15 UTC
2020-04-01 11:39:27 UTC
2020-04-01 11:39:41 UTC
2020-04-01 11:39:47 UTC
2020-04-01 11:39:54 UTC
2020-04-01 11:40:00 UTC
2020-04-01 11:40:28 UTC
2020-04-01 17:30:28 UTC
2020-04-01 17:36:18 UTC
2020-04-02 00:26:18 UTC
2020-04-02 00:28:46 UTC
2020-04-02 00:29:20 UTC
2020-04-02 00:29:28 UTC
2020-04-02 00:29:34 UTC
2020-04-02 00:29:41 UTC
2020-04-02 00:29:47 UTC
2020-04-02 00:30:01 UTC
2020-04-02 00:30:07 UTC
2020-04-02 00:30:21 UTC
2020-04-02 00:30:27 UTC
2020-04-02 00:30:35 UTC
2020-04-02 00:30:42 UTC
2020-04-02 00:30:48 UTC
2020-04-02 00:30:55 UTC
2020-04-02 00:31:01 UTC
2020-04-02 00:31:15 UTC
BatchID(фрейм данных):
Batch Id dateTime nextDate
ABC053272A 2020-04-01 00:00:48 UTC 2020-04-02 00:29:47 UTC
ABC053314A 2020-04-02 00:29:47 UTC 2020-04-03 00:12:58 UTC
ABC053330A 2020-04-03 00:12:58 UTC 2020-04-04 01:16:54 UTC
ABC053355A 2020-04-04 01:16:54 UTC 2020-04-07 00:33:57 UTC
ABC053405A 2020-04-07 00:33:57 UTC 2020-04-08 00:46:47 UTC
ABC053421A 2020-04-08 00:46:47 UTC 2020-04-09 00:36:56 UTC
ABC053447A 2020-04-09 00:36:56 UTC 2020-04-10 01:26:55 UTC
ABC053462A 2020-04-10 01:26:55 UTC 2020-04-13 08:13:50 UTC
ABC053470 2020-04-13 08:13:50 UTC 2020-04-14 10:07:56 UTC
ABC053496A 2020-04-14 10:07:56 UTC 2020-04-15 11:08:59 UTC
ABC053520A 2020-04-15 11:08:59 UTC 2020-04-16 17:51:28 UTC
ABC053553A 2020-04-16 17:51:28 UTC 2020-04-20 04:24:53 UTC
ABC053611A 2020-04-20 04:24:53 UTC 2020-04-22 00:09:56 UTC
ABC053652A 2020-04-22 00:09:56 UTC 2020-04-22 12:05:49 UTC
ABC053652B 2020-04-22 12:05:49 UTC 2020-04-23 14:12:53 UTC
ABC053686 2020-04-23 14:12:53 UTC 2020-04-24 12:14:55 UTC
ABC053694A 2020-04-24 12:14:55 UTC 2020-04-28 00:08:59 UTC
ABC053710A 2020-04-28 00:08:59 UTC 2020-04-29 00:34:56 UTC
ABC053769A 2020-04-29 00:34:56 UTC 2020-04-30 00:59:58 UTC
ABC053793A 2020-04-30 00:59:58 UTC 2020-05-01 00:41:54 UTC
ABC053827A 2020-05-01 00:41:54 UTC 2020-05-05 00:53:55 UTC
ABC053876A 2020-05-05 00:53:55 UTC 2020-05-06 04:10:55 UTC
ABC053892A 2020-05-06 04:10:55 UTC 2020-05-07 06:22:56 UTC
ABC053918A 2020-05-07 06:22:56 UTC 2020-05-08 06:02:55 UTC
ABC053942A 2020-05-08 06:02:55 UTC 2020-05-11 06:43:42 UTC
ABC053967A 2020-05-11 06:43:42 UTC 2020-05-12 07:01:57 UTC
ABC053991A 2020-05-12 07:01:57 UTC 2020-05-13 05:08:47 UTC
ABC054007A 2020-05-13 05:08:47 UTC 2020-05-14 03:36:55 UTC
ABC054023A 2020-05-14 03:36:55 UTC 2020-05-15 02:32:58 UTC
ABC054064A 2020-05-15 02:32:58 UTC 2020-05-18 04:32:57 UTC
Я пытаюсь получить значения из столбца идентификатора пакета (фрейм данных BatchID) в столбец идентификатора пакета (фрейм данных Time) на основе того, находится ли CentralTime (фрейм данных Time) между DateTime (фрейм данных BatchID) и nextDate (фрейм данных BatchID)
Я использую цикл «for» для получения этих значений, но это занимает слишком много времени. пытаюсь найти альтернативное решение. Я только что опубликовал подмножество данных из того, что у меня есть. Ниже приведен код.
if(nrow(BatchId)!=0){
for(i in 1:nrow(Time)){
for(j in 1:nrow(BatchId)){
if (Time[i,"CentralTime"] < BatchId[j,"nextDate"] amp;
Time[i,"CentralTime"]> BatchId[j,"dateTime"]) {
Time[i,"batchId"]<-BatchId[j,"Batch Id"]
}
}
}
}
Комментарии:
1. Ваши данные выборки дают нулевые совпадения.
2. @r2evans-отредактировано время (df)
Ответ №1:
Редко двойной for
цикл является необходимым (или даже целесообразным) способом решения проблем в R, и это не исключение. Фактически, это вызывает соединение «неравенство». База R его не поддерживает, и, хотя dplyr
поддерживает его при подключении dbplyr::sql_on
, я предлагаю data.table
метод:
Я создам свой собственный Time
, чтобы увидеть некоторые совпадения:
library(data.table)
Time <- data.frame(CentralTime = BatchId$dateTime[3] c(0, 1000, 3000, 9000))
Time
# CentralTime
# 1: 2020-04-03 00:12:58
# 2: 2020-04-03 00:29:38
# 3: 2020-04-03 01:02:58
# 4: 2020-04-03 02:42:58
Я предполагаю, что ни один фрейм data.table
не относится к классу, поэтому я буду немного осторожен. (Если вы уже используете data.table
, то вы, вероятно, знаете, что можно удалить из этого кода. Если нет, то (1) data.table
работает на месте, в отличие от семантики копирования при записи по умолчанию R; (2) для этого требуется другой атрибут (адрес памяти), который должен быть установлен до data.table
того, как операторы будут работать с ним; и setDT
и setDF
изменить на и из этого формата, соответственно. Я не рекомендую сохранять его как фрейм data.table
класса a, если вы ничего не data.table
делаете с ним и с ним, поскольку есть некоторые базовые R-фреймы, поведение которых меняется.)
library(data.table)
setDT(BatchId)
setDT(Time)
out <- BatchId[Time, on = .(dateTime <= CentralTime, nextDate >= CentralTime)]
out <- out[, .(CentralTime = dateTime, BatchId)]
setDF(out)
out
# CentralTime BatchId
# 1 2020-04-03 00:12:58 ABC053314A
# 2 2020-04-03 00:12:58 ABC053330A
# 3 2020-04-03 00:29:38 ABC053330A
# 4 2020-04-03 01:02:58 ABC053330A
# 5 2020-04-03 02:42:58 ABC053330A
Некоторые заметки о том, как data.table
происходит слияние:
-
DT1[DT2, on = ...]
является левым соединением. На мгновение игнорируя неравнозначное соединение, этот метод похож на### base R merge(DT2, DT1, ...) ### dplyr right_join(DT1, DT2, ...) left_join(DT2, DT1, ...)
-
поле time в «левом» фрейме (
Time
,DT1
в моем предыдущем примере) переименовано в первое из неравнозначных полей, используемых в другом фрейме, поэтому, если вы посмотритеout
сразу после объединения, в нем есть столбцыBatchId
dateTime
(хотя эти значения не обязательно равны любомувнутриBatchId$dateTime
… сбивает с толку), иnextDate
И не уникально для data.table
, это соединение создает две строки за один раз, поскольку идентификаторы ABC053314A
и ABC053330A
перекрываются:
subset(BatchId, BatchId %in% c("ABC053314A", "ABC053330A"))
# BatchId dateTime nextDate
# 1: ABC053314A 2020-04-02 00:29:47 2020-04-03 00:12:58
# 2: ABC053330A 2020-04-03 00:12:58 2020-04-04 01:16:54
a <- subset(BatchId, BatchId %in% c("ABC053314A", "ABC053330A"))
a$nextDate[1] == a$dateTime[2]
# [1] TRUE
(которые не всегда могут быть абсолютно равными, поскольку они фактически являются числами с плавающей запятой).
Если у вас есть строгое неравенство с одной стороны, это уменьшает это расширение:
setDT(BatchId)
setDT(Time)
out <- BatchId[Time, on = .(dateTime <= CentralTime, nextDate > CentralTime)]
out <- out[, .(CentralTime = dateTime, BatchId)]
setDF(out)
out
# CentralTime BatchId
# 1 2020-04-03 00:12:58 ABC053330A
# 2 2020-04-03 00:29:38 ABC053330A
# 3 2020-04-03 01:02:58 ABC053330A
# 4 2020-04-03 02:42:58 ABC053330A
### cleanup
setDF(BatchId)
setDF(Time)
Данные:
BatchId <- read.table(header = TRUE, sep = "|", text = "
BatchId | dateTime | nextDate
ABC053272A | 2020-04-01 00:00:48 UTC | 2020-04-02 00:29:47 UTC
ABC053314A | 2020-04-02 00:29:47 UTC | 2020-04-03 00:12:58 UTC
ABC053330A | 2020-04-03 00:12:58 UTC | 2020-04-04 01:16:54 UTC
ABC053355A | 2020-04-04 01:16:54 UTC | 2020-04-07 00:33:57 UTC
ABC053405A | 2020-04-07 00:33:57 UTC | 2020-04-08 00:46:47 UTC
ABC053421A | 2020-04-08 00:46:47 UTC | 2020-04-09 00:36:56 UTC
ABC053447A | 2020-04-09 00:36:56 UTC | 2020-04-10 01:26:55 UTC
ABC053462A | 2020-04-10 01:26:55 UTC | 2020-04-13 08:13:50 UTC
ABC053470 | 2020-04-13 08:13:50 UTC | 2020-04-14 10:07:56 UTC
ABC053496A | 2020-04-14 10:07:56 UTC | 2020-04-15 11:08:59 UTC
ABC053520A | 2020-04-15 11:08:59 UTC | 2020-04-16 17:51:28 UTC
ABC053553A | 2020-04-16 17:51:28 UTC | 2020-04-20 04:24:53 UTC
ABC053611A | 2020-04-20 04:24:53 UTC | 2020-04-22 00:09:56 UTC
ABC053652A | 2020-04-22 00:09:56 UTC | 2020-04-22 12:05:49 UTC
ABC053652B | 2020-04-22 12:05:49 UTC | 2020-04-23 14:12:53 UTC
ABC053686 | 2020-04-23 14:12:53 UTC | 2020-04-24 12:14:55 UTC
ABC053694A | 2020-04-24 12:14:55 UTC | 2020-04-28 00:08:59 UTC
ABC053710A | 2020-04-28 00:08:59 UTC | 2020-04-29 00:34:56 UTC
ABC053769A | 2020-04-29 00:34:56 UTC | 2020-04-30 00:59:58 UTC
ABC053793A | 2020-04-30 00:59:58 UTC | 2020-05-01 00:41:54 UTC
ABC053827A | 2020-05-01 00:41:54 UTC | 2020-05-05 00:53:55 UTC
ABC053876A | 2020-05-05 00:53:55 UTC | 2020-05-06 04:10:55 UTC
ABC053892A | 2020-05-06 04:10:55 UTC | 2020-05-07 06:22:56 UTC
ABC053918A | 2020-05-07 06:22:56 UTC | 2020-05-08 06:02:55 UTC
ABC053942A | 2020-05-08 06:02:55 UTC | 2020-05-11 06:43:42 UTC
ABC053967A | 2020-05-11 06:43:42 UTC | 2020-05-12 07:01:57 UTC
ABC053991A | 2020-05-12 07:01:57 UTC | 2020-05-13 05:08:47 UTC
ABC054007A | 2020-05-13 05:08:47 UTC | 2020-05-14 03:36:55 UTC
ABC054023A | 2020-05-14 03:36:55 UTC | 2020-05-15 02:32:58 UTC
ABC054064A | 2020-05-15 02:32:58 UTC | 2020-05-18 04:32:57 UTC")
BatchId[c("dateTime", "nextDate")] <-
lapply(BatchId[c("dateTime", "nextDate")], as.POSIXct, tz = "UTC")
Комментарии:
1. @r2evans- все строки в BatchID df уникальны.
2. Я никогда не говорил, что у вас есть повторяющиеся строки
BatchId
. Я определил ситуацию, когда два пакета совместно используют endpoint (dateTime[n 1] == nextDate[n]
), которая выдает выходные данные, показывающие два идентичныхBatchId
значения. Разные операторы (и разрешены). Дает ли это ожидаемый результат?3. @r2evans — не получение ожидаемого выходного столбца CentralTime во времени (df) по сравнению с этими столбцами nextDate (столбец в BatchID df) и DateTime (столбец в BatchID df) не будут иметь одинаковых значений. не будет выдавать никаких совпадающих значений, используя этот код out <- out[, .(CentralTime = DateTime, BatchID)]
4. Значит, ваш
out
телефон пуст? Когда я использовал ваши данные, они были пустыми для меня, и это было потому, что ваши данные не имеют совпадений.5. я вовремя изменил данные (df), пожалуйста, проверьте эти данные
Ответ №2:
Игнорируя ошибку с вашей проблемой, вы можете полностью удалить один цикл. Однако неясно, чего следует ожидать в случае, когда оператор имеет несколько совпадений.
if(nrow(BatchId)!=0){
for(i in 1:nrow(Time)){
idx <- which(Time[i,"CentralTime"] < BatchId[,"nextDate"] amp;
Time[i,"CentralTime"] > BatchId[,"dateTime"])
if(length(idx) > 1)
stop('more than one match what should I do?')
Time[i, 'batchId'] <- BatchId[idx, "Batch Id"]
}
}
однако ответ @revans является лучшим вариантом как для скорости, так и для использования памяти.
Комментарии:
1. @Oliver — ошибка получения —- » определено только для фреймов данных одинакового размера »
2. С вашими примерами данных я не могу воспроизвести ошибку. 🙂