2017-01-17 23 views
1

Я работаю с набором данных почасовой температуры, и мне нужно рассчитать «часы градуса» выше порога тепла для каждого экстремального события. Я намерен запускать статистику по интенсивностям (объединенной величине и продолжительности) каждого события для сравнения нескольких сайтов за тот же период времени.Добавить последовательные значения температуры выше порогового значения для создания «часов градуса»

Пример данных:

 Temp 
1  14.026 
2  13.714 
3  13.25 
..... 
21189 12.437 
21190 12.558 
21191 12.703 
21192 12.896 

данных после выбора только часов выше порога 18 градусов, а затем вычесть 18, чтобы показать градусов выше 18:

 Temp 
5297 0.010 
5468 0.010 
5469 0.343 
5470 0.081 
5866 0.010 
5868 0.319 
5869 0.652 

После этого шага мне нужна помощь сумма последовательных часов, в течение которых показания превысили мой указанный порог.

То, что я надеюсь, чтобы произвести из выше образца:

 Temp 
    1 0.010 
    2 0.434 
    3 0.010 
    4 0.971 

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

ответ

0

Для этого, пожалуйста, используйте data.table, хотя есть и другие способы.

library(data.table) 
setDT(df) 
temp.threshold <- 18 

Сначала сделайте столбец, показывающий предыдущего значения из каждого в ваших данных. Это поможет найти точку, в которой температура повысилась выше вашего порогового значения.

df[ , lag := shift(Temp, fill = 0, type = "lag") ] 

Теперь использовать эту предыдущую колонку значения для сравнения с Temp колонки. Отметьте каждую точку, при которой температура поднялась выше порога с 1, а все остальные точки как 0.

df[ , group := 0L 
    ][ Temp > temp.threshold & lag <= temp.threshold, group := 1L ] 

Теперь мы можем получить cumsum этого нового столбца, который даст каждой последовательности после того, как температура поднялась выше порог его собственный group ID.

df[ , group := cumsum(group) ] 

Теперь мы можем избавиться от каждого значения не выше порога.

df <- df[ Temp > temp.threshold, ] 

И суммируйте то, что осталось, найдя «часы градуса» каждой «группы».

bygroup <- df[ , sum(Temp - temp.threshold), by = group ] 

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

structure(list(num = c(1L, 2L, 3L, 4L, 5L, 21189L, 21190L, 21191L, 
21192L, 21193L, 21194L), Temp = c(14.026, 13.714, 13.25, 20, 
19, 12.437, 12.558, 12.703, 12.896, 21, 21)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -11L), .Names = c("num", 
"Temp"), spec = structure(list(cols = structure(list(num = structure(list(), class = c("collector_integer", 
"collector")), Temp = structure(list(), class = c("collector_double", 
"collector"))), .Names = c("num", "Temp")), default = structure(list(), class = c("collector_guess", 
"collector"))), .Names = c("cols", "default"), class = "col_spec")) 

С этими данными, вот вывод кода выше (обратите внимание $V1 является в "градусных часов"):

> bygroup 
    group V1 
1:  1 3 
2:  2 6 
0

Это альтернативное решение в базе R.

У вас есть данные, которые ходят, и вы хотите подытожить точки над отсечкой.Например:

set.seed(99999) 
x <- cumsum(rnorm(30)) 
plot(x, type='b') 
abline(h=2, lty='dashed') 

, который выглядит следующим образом:

enter image description here

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

x.rle <- rle(x > 2) 

, который имеет значение:

Run Length Encoding 
    lengths: int [1:8] 5 2 3 1 9 4 5 1 
    values : logi [1:8] FALSE TRUE FALSE TRUE FALSE TRUE ... 

Первая группа первые 5 точек, где х> 2 ложна; вторая группа - две следующие точки и т. д.

Мы можем создать идентификатор группы, заменив значения в объекте РЛЭ, а затем обратно трансформации:

x.rle$values <- seq_along(x.rle$values) 
group <- inverse.rle(x.rle) 

Наконец, мы собираем по группам, сохраняя данные только над отрезан:

aggregate(x~group, subset = x > 2, FUN=sum) 

Который производит:

group   x 
1  2 5.113291213 
2  4 2.124118005 
3  6 11.775435706 
4  8 2.175868979