Разделите временные ряды на определенные ячейки и пометьте каждый фрагмент

#r #dplyr

#r #dplyr

Вопрос:

У меня есть некоторые экспериментальные данные о значениях CO2 за несколько дней в комнате, которые помечены временем и датой. Я хотел бы разбить его на серию «экспериментов» на основе списка экспериментов, когда происходил каждый эксперимент. введите описание изображения здесьнапример

Данные

 df<-data.frame(CO2.ppm.=runif(10), Date.time.=as.POSIXct(" 2019-2-08 07:00:00")   runif(n=10, min=0, max=3600))
 

Список экспериментов с указанием времени начала и окончания:

 ExpertimentList<- data.frame(StartTime=c("2019-2-08 07:10:00", "2019-2-08 07:15:00", "2019-2-08 08:30:00"), StopTime=c("2019-2-08 07:12:00","2019-2-08 07:16:00","2019-2-08 08:15:00"),ExptID=c(1,2,3))
 

Обратите внимание, что есть время, когда CO2 измеряется, но эксперимент не проводится. Например. между 07:12:00 и 07:15:00.

Я хотел бы разделить df$Date.time. на ExperimentList ‘s StartTime и StopTime

До сих пор я преобразовал все в целые числа

 df$Date.time.<-as.integer(df$Date.time.)
ExperimentList$StartTime<-as.integer(ExperimentList$StartTime
ExperimentList$StopTime<-as.integer(ExperimentList$StopTime)
 

Затем, глядя на cut

 breakz<-dplyr::arrange(paste(Experiment_List$StartTime,Experiment_List$StopTime)%>%as_tibble())

cut(df$Dev.Date.Time,breaks=unique(breakz$value))
 

Но я не могу отфильтровать данные, когда не проводился эксперимент. Любые мысли приветствуются.

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

 set.seed(143)
data.frame(CO2.ppm.=runif(10), Date.time.=sort(as.POSIXct(" 2019-2-08 07:00:00")   runif(n=10, min=0, max=3600)),ExptID=c(NA,NA,NA,1,NA,NA,NA,NA,NA,NA))
 

ОТВЕТ:

Я обнаружил, что у меня закончится память с ответом @Ronak, поэтому я разделил data.frame на 10000 сегментов строк:

 df<-split(df, (as.numeric(rownames(df))-1) %/% 10000)
 

Затем, основываясь на ответе @Ronak, я вставил код в функцию и использовал mclapply из параллельного пакета.

#Выполните левое соединение, чтобы удалить все строки, не принадлежащие эксперименту

 fuzzyJoinFunction<-function(a){
  a<-fuzzy_left_join(a, Experiment_List, 
                       by = c('Dev.Date.Time' = 'StartTime', 'Dev.Date.Time'= 'StopTime'), 
                       match_fun = c(`>=`, `<=`))
  a
}

df<-rbindlist(mclapply(X=df,FUN=fuzzyJoinFunction,mc.cores=4))
 

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

1. Можете ли вы включить ожидаемый результат для совместно используемых данных?

2. Привет, Ронак, спасибо, что изучили это. Я добавил ожидаемый результат, чтобы помочь. Также добавлен set.seed и отсортировано время, потому что в противном случае оно будет меняться. Но со значениями, которые он сгенерировал, я нашел только 1 значение CO2, которое находится во время эксперимента в списке.

Ответ №1:

Мы можем использовать fuzzyjoin::fuzzy_inner_join для хранения только строк, которые находятся в диапазоне.

 library(dplyr)
library(fuzzyjoin)

#All the datetime values should be of type POSIXct.
ExpertimentList %>%
  mutate(across(c(StartTime, StopTime), lubridate::ymd_hms)) -> ExpertimentList


fuzzy_inner_join(df, ExpertimentList, 
                 by = c('Date.time.' = 'StartTime', 'Date.time.'= 'StopTime'), 
                 match_fun = c(`>=`, `<=`))
 

Чтобы получить все df значения в конечном выводе с NA помощью for ExptID use fuzzy_left_join .

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

1. Вау, это было быстро! еще до того, как я закончил писать комментарий выше!

2. Я обнаружил, что мой сеанс R работает около 30 минут, но затем выходит из строя. Я попробовал это на небольшом (1000 строк) фрагменте data.frame, и он работает хорошо, но затем выходит из строя на больших наборах (5E6 строк). Как вы думаете, какой наилучший путь вперед?

3. Я собираюсь попробовать разбить его на фрагменты, а затем связать в конце.