2013-07-29 3 views
0

J'essaie de comprendre comment faire ce qui suit sans boucler. J'ai un ensemble de données fondu de temps, le site d'étude, et le flux qui ressemble à:sous-ensemble et effectuer des calculs sur les données de séries chronologiques, en évitant les boucles

site datetime flux
6/1/2009 00:00 EBT NA
6/2/2009 01:00 EBT NA
6/3/2009 02:00 EBT 0,1
6/4/2009 03:00 EBT NA
6/5/2009 04:00 EBT NA
6/1/2009 00:00 MUT 0,4
6/2/2009 01:00 MUT 0.3
6/3/2009 02:00 MUT 0.2
6/4/2009 03:00 MUT NA
6/5/2009 04:00 MUT NA

je dois sous-ensemble par ce site, puis pendant les périodes où il y a au moins deux mesures de débit suivantes je dois effectuer quelques calculs, * par exemple la moyenne de la mesure actuelle et précédente. L'astuce est que j'ai besoin d'effectuer la moyenne sur chaque ensemble de mesures consécutives, c'est-à-dire s'il y en a trois d'affilée pour chacun des deux derniers, j'ai besoin de la moyenne de cette mesure et de la précédente. J'ai ajouté une colonne d'objectif à l'exemple de base de données avec les résultats que j'aimerais obtenir. *

J'aimerais disposer d'une zone de données similaire avec le datetime, le site et le résultat du calcul. Il y a une série à temps plein pour chaque site.

Merci pour toute aide!

générateur de données:

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

Pouvez-vous fournir l'ensemble de données que vous recherchez? Vous pouvez le faire facilement avec de nombreux outils dans R ... 'library (data.table); s = data.table (échantillon); s [, mean (flow), by = site] '... – Justin

+0

La question éditée doit être plus claire et ajouter un exemple de sortie. Merci! –

Répondre

1

Cela se sépareront votre dataframe par site puis filtrer uniquement les lignes qui ont deux ou plusieurs consécutifs valeurs non-NA dans flow:

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

Vous pouvez alors travailler sur la fonction à l'intérieur pour faire vos calculs au besoin.

Par exemple, si vous voulez ajouter la moyenne comme une nouvelle colonne (en supposant que vous voulez NA lorsque non défini), vous pouvez utiliser ceci:

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) 

Résultat:

   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: Pour obtenir la moyenne entre la mesure de débit actuelle et la précédente, vous pouvez utiliser ceci:

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

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

Notez que les observations avec une seule mesure sont automatiquement définies sur NA. Nouveau résultat:

   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

Ferdinand, c'est très proche. Merci! Cependant, cela calcule la moyenne pour tous les flux par site qui répondent aux critères. Ce que j'aurais dû être plus clair, c'est que j'ai besoin d'effectuer le calcul sur chaque ensemble. J'ai édité la question pour être plus clair et ajouté quelques données à l'ensemble de l'échantillon, avec quelle sortie je vis. Merci encore! –

+0

@IcebergSlim, j'ai édité la réponse en conséquence. –

0

Les fonctions Plyr sont un bon moyen de séparer les données de certaines variables, ce que vous devez faire.

J'ai pensé à deux façons de gérer les intervalles sur un vecteur: d'abord avec la multiplication vectorielle (pour la moyenne des données), et ensuite avec la vectorisation d'une fonction (pour générer les étiquettes). Ils font tous deux à peu près la même chose, cependant.

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 
Questions connexes