Я сталкиваюсь с ошибкой в R при попытке выполнить цикл во времени. Вот подмножество моего фрейма данных (содержащего 120000 строк).
time value mean group
1 2017-01-01 12:00:00 0.507 0.5106533 NA
2 2017-01-01 12:05:00 0.526 0.5106533 NA
3 2017-01-01 12:10:00 0.489 0.5106533 NA
4 2017-01-01 12:15:00 0.598 0.5106533 NA
5 2017-01-01 12:20:00 0.564 0.5106533 NA
6 2017-01-01 12:25:00 0.536 0.5106533 NA
Допустим, я хочу создавать группы на основе периода времени с ожидаемым результатом, подобным этому:
time value mean group
1 2017-01-01 12:00:00 0.507 0.5106533 A
2 2017-01-01 12:05:00 0.526 0.5106533 A
3 2017-01-01 12:10:00 0.489 0.5106533 B
4 2017-01-01 12:15:00 0.598 0.5106533 B
5 2017-01-01 12:20:00 0.564 0.5106533 C
6 2017-01-01 12:25:00 0.536 0.5106533 C
Я пробовал следующий код:
for (i in 1:length(merged.data$group)){
if (merged.data[as.POSIXlt(i)$time >= "2017-05-15 12:00:00 GMT" &
as.POSIXlt(i)$time <= "2017-05-29 12:00:00 GMT",]){
merged.data$group == "A"}
else if (merged.data[as.POSIXlt(i)$time >= "2017-08-11 12:00:00" &
as.POSIXlt(i)$time <= "2017-11-29 16:00:00",]){
merged.data$group == "B"}
else if (merged.data[as.POSIXlt(i)$time >= "2018-01-05 12:00:00" &
as.POSIXlt(i)$time <= "2018-02-16 16:00:00",]){
merged.data$group == "C"}
}
Я получаю следующую ошибку:
Error in as.POSIXlt.numeric(i) : 'origin' must be supplied
Я не понимаю, я думал, что POSIXlt избавлялся от проблем с исходным кодом? Хотя я признаю, что мое понимание проблем времени в R немного сбивает с толку, и мне сложно кодировать каждый раз, когда мне нужно иметь дело со временем / датами ...
Так что я надеюсь, что кто-то может мне помочь, не стесняйтесь сказать мне, если я не понимаю, или если для ответа на мой вопрос требуется дополнительная / лучшая информация.
Спасибо заранее, stackoverflowers!
as.POSIXlt(i) не работает, поскольку i - это просто целое число, так как вы зацикливаетесь с 1:length(merged.data$group). Если вы собираетесь вызвать в as.POSIXlt(i), то вам нужно убедиться, что i - это свидание.
Группы, которые я хочу создать, включаются между датами. Спасибо за ответ, Сотос, ты ясно дал понять, что я запутался в этой проблеме с датой и временем! Я попытаюсь изменить свой код и поставить i в качестве даты, как предлагает shwan (thx btw). Поправлю в своем вопросе, но предложения все равно интересны.





data.table подход ...
Пример данных
library( data.table )
dt <- fread("time value mean
2017-01-01T12:00:00 0.507 0.5106533
2017-01-01T12:05:00 0.526 0.5106533
2017-01-01T12:10:00 0.489 0.5106533
2017-01-01T12:15:00 0.598 0.5106533
2017-01-01T12:20:00 0.564 0.5106533
2017-01-01T12:25:00 0.536 0.5106533 ", header = TRUE)
dt[, time := as.POSIXct( time, format = "%Y-%m-%dT%H:%M:%S" )]
код
library( data.table )
library( lubridate )
dt[, group := LETTERS[.GRP], by = lubridate::floor_date( time, "10 mins" ) ]
# time value mean group
# 1: 2017-01-01 12:00:00 0.507 0.5106533 A
# 2: 2017-01-01 12:05:00 0.526 0.5106533 A
# 3: 2017-01-01 12:10:00 0.489 0.5106533 B
# 4: 2017-01-01 12:15:00 0.598 0.5106533 B
# 5: 2017-01-01 12:20:00 0.564 0.5106533 C
# 6: 2017-01-01 12:25:00 0.536 0.5106533 C
подход с использованием foverlaps, основанный на предоставленных образцах данных и кода
library( data.table )
#create lookup-table with periods and group-names
periods.dt <- data.table(
start = as.POSIXct( c( "2017-05-15 12:00:00", "2017-08-11 12:00:00", "2018-01-05 12:00:00" ), tz = "GMT" ),
stop = as.POSIXct( c( "2017-08-11 12:00:00", "2018-01-05 12:00:00", "2018-02-16 16:00:00"), tz = "GMT" ),
group = LETTERS[1:3] )
#set keys
setkey( periods.dt, start, stop )
#create sample data
dt <- fread("time value mean
2017-01-01T12:00:00 0.507 0.5106533
2017-01-01T12:05:00 0.526 0.5106533
2017-01-01T12:10:00 0.489 0.5106533
2017-01-01T12:15:00 0.598 0.5106533
2017-01-01T12:20:00 0.564 0.5106533
2017-01-01T12:25:00 0.536 0.5106533 ", header = TRUE)
dt[, time := as.POSIXct( time, format = "%Y-%m-%dT%H:%M:%S", tz = "GMT" )]
#create dummies to join on
dt[, `:=`( start = time, stop = time )]
#perform overlap join, no match --> NA
foverlaps( dt, periods.dt, type = "within", nomatch = NA)[, c("time", "value","mean","group"), with = FALSE]
# time value mean group
# 1: 2017-01-01 12:00:00 0.507 0.5106533 <NA>
# 2: 2017-01-01 12:05:00 0.526 0.5106533 <NA>
# 3: 2017-01-01 12:10:00 0.489 0.5106533 <NA>
# 4: 2017-01-01 12:15:00 0.598 0.5106533 <NA>
# 5: 2017-01-01 12:20:00 0.564 0.5106533 <NA>
# 6: 2017-01-01 12:25:00 0.536 0.5106533 <NA>
Большое спасибо, это действительно хорошо, но не совсем соответствует тому, что я хочу, но, возможно, я недостаточно ясно показал свой пример. Мой фрейм данных относительно огромен (12000 строк), и мне нужно, чтобы мои группы определялись датами, а не периодом времени, потому что он соответствует конкретным измерениям запуска / остановки зондов. Я понятнее? (извините, всегда сложно просто объяснить что-то странное, что вы делаете ^^).
@ DocMartin: Нет, мне непонятно, как вы определяете свои группы ... С группами в отдельной таблице, вероятно, лучше всего подойдет data.table::foverlaps(). Все даты в цикле for ваших вопросов не соответствуют вашим выборочным данным.
Спасибо за быстрый ответ и кодирование. Это заняло у меня некоторое время, но я понимаю код, и он отлично работает с вашими примерами данных. У меня проблема с моими собственными данными, я получаю следующее сообщение, когда пытаюсь преобразовать мой df в data.table: Ошибка в dimnames (x) <- dn: length of 'dimnames' [1] не равно размеру массива Мне нужно больше узнать о data.table, потому что я видел много тем, использующих его, я привык только к фреймам данных. Еще раз спасибо за ваше время !
@ DocMartin сложно сказать без выборочных данных ваших производственных данных ... Возможно, будет бесполезно задавать новый вопрос по SO, касающемуся вашей проблемы ... не забудьте включить образцы данных с использованием dput(), чтобы мы знали, с чем вы работаете. .
Я вернулся, чтобы поблагодарить вас еще раз, Вымпел, теперь все в порядке, я понял, что не так, и могу использовать ваше решение, которое отлично работает! С уважением,
Спасибо за ответ, я обнаружил, что мне пригодилась только дата, так как в моем наборе данных были огромные пробелы. С помощью простого ifelse я обнаружил, что что-то работает:
merged.data$group<-ifelse(merged.data$date >= "2017-05-15" & merged.data$date <= "2017-05-29",1, ifelse(merged.data$date >= "2017-08-11" & merged.data$date <= "2017-11-29",2, ifelse(merged.data$date >= "2018-01-05" & merged.data$date <= "2018-02-16",3, NA )))
Это не работает с объектами POSIXlt, которые у меня были, но решение, предоставленное Wimpel, похоже, работает (у меня проблема с использованием data.table, но это уже другая история!)
Еще раз спасибо, этот форум действительно очень помогает!
какие условия для ваших групп? Также этот
as.POSIXlt(i)$timeне является действительным кодом R. Вдобавок,for i in 1:length(..), так что вашiцелочислен, и вы пытаетесь преобразовать его во время ... Вы, вероятно, имеете в видуas.POSIXlt$time[i], ноas.POSIXct()векторизован. Плюс, даже если вы конвертируете его во время, вы затем сравниваете его с символом ("2017-05-15 12:00:00 GMT") ...