2013-07-29 4 views
0

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

поток Дата и время на сайте
6/1/2009 00:00 EBT Н.А.
6/2/2009 01:00 EBT Н.А.
6/3/2009 02:00 ЕВТ 0,1
6/4/2009 03:00 ЕВТ Н.А.
6/5/2009 04:00 ЕВТ Н.А.
6/1/2009 00:00 MUT 0,4
06.06.2009 01:00 MUT 0,3
06.06.2009 02:00 MUT 0,2
6/4/2009 3:00 MUT Н.А.
6/5/2009 04:00 MUT Н.А.

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

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

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

Спасибо за помощь!

генератор

данные:

structure(list(datetime = structure(c(1167627600, 1167717600, 
1167807600, 1167897600, 1167987600, 1167627600, 1167717600, 1167807600, 
1167897600, 1167987600, 1168077600, 1168167600, 1168257600, 1168347600, 
1168437600), class = c("POSIXct", "POSIXt"), tzone = ""), site = structure(c(1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("EBT", 
"MUT"), class = "factor"), flow = c(NA, 0.1, NA, NA, NA, NA, 
0.4, 0.2, NA, NA, 0.4, 0.2, 0.1, NA, NA), goal = c(NA, NA, NA, 
NA, NA, NA, NA, 0.3, NA, NA, NA, 0.3, 0.15, NA, NA)), .Names = c("datetime", 
"site", "flow", "goal"), row.names = c(NA, -15L), class = "data.frame") 
+2

Можете ли вы предоставить результирующий набор данных, который вы ищете? Вы можете сделать это легко со многими инструментами в библиотеке R ... '(data.table); s = data.table (образец); s [, mean (flow), by = site] '... – Justin

+0

Отредактированный вопрос должен быть более четким и добавить образец вывода. Благодаря! –

ответ

1

Это отделить dataframe от site, а затем фильтровать только те строки, которые имеют два или более последовательных значений не-NA в flow:

by(sample, sample$site, function(d) d[with(rle(!is.na(d$flow)), rep(values & lengths>=2, lengths)),]) 

Вы можете работать на функцию внутри, чтобы делать ваши вычисления по мере необходимости.

Например, если вы хотите добавить среднее значение как новый столбец (если вы хотите NA, когда не определено), вы можете использовать это:

f <- function(d) 
{ 
    x <- with(rle(!is.na(d$flow)), rep(values & lengths>=2, lengths)) 

    within(d, {avg <- NA; avg[x] <- mean(d[x,"flow"])}) 
} 

b <- by(sample, sample$site, f) 

Reduce(rbind, b) 

Результат:

   datetime site flow avg 
1 2009-06-01 01:00:00 EBT NA NA 
2 2009-06-02 02:00:00 EBT NA NA 
3 2009-06-03 03:00:00 EBT 0.1 NA 
4 2009-06-04 04:00:00 EBT NA NA 
5 2009-06-05 05:00:00 EBT NA NA 
6 2009-06-01 01:00:00 MUT 0.4 0.3 
7 2009-06-02 02:00:00 MUT 0.3 0.3 
8 2009-06-03 03:00:00 MUT 0.2 0.3 
9 2009-06-04 04:00:00 MUT NA NA 
10 2009-06-05 05:00:00 MUT NA NA 

EDIT: Чтобы получить среднее значение между текущим измерением расхода и предыдущим, вы можете использовать это:

f <- function(d) 
{ 
    within(d, avg <- (flow+c(NA,head(flow,-1)))/2) 
} 

Reduce(rbind, by(sample, sample$site, f)) 

Обратите внимание, что в случае с одной мерой автоматически устанавливается значение NA. Новый результат:

   datetime site flow goal avg 
1 2007-01-01 03:00:00 EBT NA NA NA 
2 2007-01-02 04:00:00 EBT 0.1 NA NA 
3 2007-01-03 05:00:00 EBT NA NA NA 
4 2007-01-04 06:00:00 EBT NA NA NA 
5 2007-01-05 07:00:00 EBT NA NA NA 
6 2007-01-01 03:00:00 MUT NA NA NA 
7 2007-01-02 04:00:00 MUT 0.4 NA NA 
8 2007-01-03 05:00:00 MUT 0.2 0.30 0.30 
9 2007-01-04 06:00:00 MUT NA NA NA 
10 2007-01-05 07:00:00 MUT NA NA NA 
11 2007-01-06 08:00:00 MUT 0.4 NA NA 
12 2007-01-07 09:00:00 MUT 0.2 0.30 0.30 
13 2007-01-08 10:00:00 MUT 0.1 0.15 0.15 
14 2007-01-09 11:00:00 MUT NA NA NA 
15 2007-01-10 12:00:00 MUT NA NA NA 
+0

Фердинанд, это очень близко. Благодаря! Тем не менее, это вычисляет среднее значение по всем потокам на сайт, которые соответствуют критериям. То, что мне должно было быть понятнее, это то, что мне нужно выполнить вычисления на каждом наборе. Я отредактировал вопрос, чтобы быть более четким, и добавил некоторые данные к набору образцов, а также то, что я делаю для съемки. Еще раз спасибо! –

+0

@IcebergSlim, я отредактировал ответ соответственно. –

0

Функции Plyr - это хороший способ разделить части данных на определенные переменные, что и нужно делать.

Я думал о двух способах обработки интервалов по вектору: сначала с векторным умножением (для среднего значения данных), а во-вторых с векторизации функции (для генерации меток). Тем не менее, они оба делают почти то же самое.

library(reshape2) 
library(plyr) 
library(lubridate) 

meanBetween <- function(x){ 
    l <- length(x) 
    diag(outer(x[1:(l-1)], x[2:l], "+"))/2 
} 

output <- ddply(sample, .(site), function(df){ 
    df <- df[order(df$datetime, decreasing=FALSE), ] 
    result <- meanBetween(df$flow) 
    names(result) <- Reduce(c, (mapply(as.interval, 
            df$datetime[-1], 
            df$datetime[1:(length(df$datetime)-1)], 
            SIMPLIFY=FALSE))) 
    result 
}) 

melt(output) # to make it look nicer 
Смежные вопросы