#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. Я собираюсь попробовать разбить его на фрагменты, а затем связать в конце.