R: фактор да-нет, основанный на предыдущих записях - PullRequest
0 голосов
/ 01 июля 2018

У меня есть набор данных временных рядов - данные с метеостанции. Итак, есть 3 столбца: time - время и дата; p - дождь, мм; h - уровень воды, м.

Мне нужно создать новый столбец factor_rain со значениями 1 и 0. 1 - если на уровень воды (df$h) повлиял дождь (df$p). Это может быть, если за последние 5 часов ( 5 записей ) был дождь. В остальных случаях должно быть 0.

Часть набора данных находится здесь:

df <- data.frame(time = c("2017-06-04 9:00:00", "2017-06-04 13:00:00",  "2017-06-04 17:00:00",
                            "2017-06-04 19:00:00",  "2017-06-04 21:00:00",  "2017-06-04 23:00:00",
                            "2017-06-05 9:00:00",   "2017-06-05 11:00:00",
                            "2017-06-05 13:00:00",  "2017-06-05 16:00:00",
                            "2017-06-05 19:00:00",  "2017-06-05 21:00:00",  "2017-06-05 23:00:00",
                            "2017-06-06 9:00:00",   "2017-06-06 11:00:00",  "2017-06-06 13:00:00",
                            "2017-06-06 16:00:00",  "2017-06-06 17:00:00",  "2017-06-06 18:00:00",
                            "2017-06-06 19:00:00"),
                   p = c(NA, NA, 16.4, NA, NA, NA, NA, NA, NA, NA, 12, 
                         NA, NA, NA, NA, NA, NA, NA, NA, NA),
                   h = c(23,NA,NA,NA,NA,32,NA,NA,28,NA,NA,
                        33,NA,NA,NA,29,NA,NA,NA,NA))

Я пробовал самый простой способ, который мне показался - к сожалению, он работает только для одного случая:

> df$factor_rain[df$p[-c(1:5)] > 1 & df$h > 1] <- 1
> Warning message:
In df$p[-c(1:5)] > 1 & df$h > 1 :
  longer object length is not a multiple of shorter object length

Есть ли способ это исправить? Если бы вы могли предложить, как использовать реальное время (например, из xts библиотеки), было бы здорово. Я имею в виду использование 5 часового порога, а не 5 значений.

Кстати, мне нужно получить это в результате:

> df
                  time    p  h factor_rain
1   2017-06-04 9:00:00   NA 23           0
2  2017-06-04 13:00:00   NA NA           0
3  2017-06-04 17:00:00 16.4 NA           0
4  2017-06-04 19:00:00   NA NA           0
5  2017-06-04 21:00:00   NA NA           0
6  2017-06-04 23:00:00   NA 32           1
7   2017-06-05 9:00:00   NA NA           0
8  2017-06-05 11:00:00   NA NA           0
9  2017-06-05 13:00:00   NA 28           0
10 2017-06-05 16:00:00   NA NA           0
11 2017-06-05 19:00:00 12.0 NA           0
12 2017-06-05 21:00:00   NA 33           1
13 2017-06-05 23:00:00   NA NA           0
14  2017-06-06 9:00:00   NA NA           0
15 2017-06-06 11:00:00   NA NA           0
16 2017-06-06 13:00:00   NA 29           0
17 2017-06-06 16:00:00   NA NA           0
18 2017-06-06 17:00:00   NA NA           0
19 2017-06-06 18:00:00   NA NA           0
20 2017-06-06 19:00:00   NA NA           0

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Решение может быть достигнуто с помощью non-equi join из data.table.

library(data.table)

df$time <- as.POSIXct(df$time, format = "%Y-%m-%d %H:%M:%S")

setDT(df)
df[,timeLow := time-5*60*60]

df[df,.(time, p, h = i.h), on=.(time < time, time >= timeLow)][
  ,.(factor_rain = ifelse(!is.na(first(h)), any(!is.na(p)),FALSE)),by=.(time)][
    df,.(time, p, h, factor_rain),on="time"]

#                   time    p  h factor_rain
# 1: 2017-06-04 09:00:00   NA 23       FALSE
# 2: 2017-06-04 13:00:00   NA NA       FALSE
# 3: 2017-06-04 17:00:00 16.4 NA       FALSE
# 4: 2017-06-04 19:00:00   NA NA       FALSE
# 5: 2017-06-04 21:00:00   NA NA       FALSE
# 6: 2017-06-04 23:00:00   NA 32       FALSE   <-- There is no rain in last 5 hours
# 7: 2017-06-05 09:00:00   NA NA       FALSE
# 8: 2017-06-05 11:00:00   NA NA       FALSE
# 9: 2017-06-05 13:00:00   NA 28       FALSE
# 10: 2017-06-05 16:00:00   NA NA       FALSE
# 11: 2017-06-05 19:00:00 12.0 NA       FALSE
# 12: 2017-06-05 21:00:00   NA 33        TRUE
# 13: 2017-06-05 23:00:00   NA NA       FALSE
# 14: 2017-06-06 09:00:00   NA NA       FALSE
# 15: 2017-06-06 11:00:00   NA NA       FALSE
# 16: 2017-06-06 13:00:00   NA 29       FALSE
# 17: 2017-06-06 16:00:00   NA NA       FALSE
# 18: 2017-06-06 17:00:00   NA NA       FALSE
# 19: 2017-06-06 18:00:00   NA NA       FALSE
# 20: 2017-06-06 19:00:00   NA NA       FALSE

Примечание: Решение можно немного оптимизировать. Я займусь оптимизацией через некоторое время.

0 голосов
/ 01 июля 2018

Вы можете использовать

df$factorrain = FALSE
df$factorrain[rowSums(expand.grid(which(!is.na(df$p)), 0:4))] = TRUE

#                   time    p  h factorrain
# 1   2017-06-04 9:00:00   NA 23   FALSE
# 2  2017-06-04 13:00:00   NA NA   FALSE
# 3  2017-06-04 17:00:00 16.4 NA    TRUE
# 4  2017-06-04 19:00:00   NA NA    TRUE
# 5  2017-06-04 21:00:00   NA NA    TRUE
# 6  2017-06-04 23:00:00   NA 32    TRUE
# 7   2017-06-05 9:00:00   NA NA    TRUE
# 8  2017-06-05 11:00:00   NA NA   FALSE
# 9  2017-06-05 13:00:00   NA 28   FALSE
# 10 2017-06-05 16:00:00   NA NA   FALSE
# 11 2017-06-05 19:00:00 12.0 NA    TRUE
# 12 2017-06-05 21:00:00   NA 33    TRUE
# 13 2017-06-05 23:00:00   NA NA    TRUE
# 14  2017-06-06 9:00:00   NA NA    TRUE
# 15 2017-06-06 11:00:00   NA NA    TRUE
# 16 2017-06-06 13:00:00   NA 29   FALSE
# 17 2017-06-06 16:00:00   NA NA   FALSE
# 18 2017-06-06 17:00:00   NA NA   FALSE
# 19 2017-06-06 18:00:00   NA NA   FALSE
# 20 2017-06-06 19:00:00   NA NA   FALSE

Или аналогичный подход с apply,

df$factorrain = FALSE
df$factorrain[sapply(which(!is.na(df$p)), function(x) x+(0:4))] = TRUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...