2017-01-17 2 views
1

Je travaille avec un jeu de données de températures horaires et j'ai besoin de calculer les «degrés-heures» au-dessus d'un seuil de chaleur pour chaque événement extrême. J'ai l'intention d'exécuter des statistiques sur les intensités (magnitude et durée combinées) de chaque événement pour comparer plusieurs sites au cours de la même période.Ajouter des valeurs de température consécutives au-dessus du seuil pour créer des «degrés-heures»

Exemple de données:

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

données après avoir sélectionné quelques heures seulement au-dessus du seuil de 18 degrés, puis en soustrayant 18 à révéler degrés au-dessus 18:

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

Après cette étape, je besoin d'aide pour somme des heures consécutives pendant lesquelles la lecture a dépassé mon seuil spécifié.

Ce que je suis l'espoir de produire de l'échantillon ci-dessus:

 Temp 
    1 0.010 
    2 0.434 
    3 0.010 
    4 0.971 

J'ai débattais la manipulation de ces données dans une série chronologique ou en ajoutant des colonnes supplémentaires, mais je ne veux pas plusieurs lignes pour chaque événement réchauffement . J'apprécierais énormément n'importe quel conseil.

Répondre

0

Je voudrais utiliser data.table pour cela, bien qu'il existe certainement d'autres façons.

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

d'abord une colonne indiquant la valeur précédente de chacun dans vos données. Cela vous aidera à trouver le point où la température a dépassé votre seuil.

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

utiliser Maintenant que la colonne de valeur précédente pour comparer avec la colonne Temp. Marquez tous les points où la température a dépassé le seuil avec un 1, et tous les autres points comme 0.

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

Maintenant, nous pouvons obtenir cumsum de cette nouvelle colonne, qui donnera chaque séquence après que la température a augmenté au-dessus du seuil son propre group ID.

df[ , group := cumsum(group) ] 

Maintenant, nous pouvons nous débarrasser de toutes les valeurs qui ne dépassent pas le seuil.

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

Et de résumer ce qui reste en trouvant les « heures de degré » de chaque « groupe ».

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

J'ai modifié vos données d'entrée un peu pour fournir quelques événements de test où les données ont dépassé le seuil:

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")) 

Avec ces données, voici la sortie du code ci-dessus (note $V1 est dans les "heures de degré"):

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

Ceci est une solution de rechange dans la base R.

Vous avez des données qui circulent et vous souhaitez résumer les points au-dessus d'un seuil.Par exemple:

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

qui ressemble à ceci:

enter image description here

D'abord, nous voulons diviser les données à des groupes quand ils traversent la coupure. Nous pouvons utiliser le codage de la longueur de course sur l'indicateur pour obtenir une version compressée:

x.rle <- rle(x > 2) 

qui a la valeur:

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 ... 

Le premier groupe est le premier 5 points où x> 2 est faux; le deuxième groupe est les deux points suivants, et ainsi de suite.

Nous pouvons créer un identifiant de groupe en remplaçant les valeurs dans l'objet RLE, puis de nouveau la transformation:

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

Enfin, nous regroupons par groupe, en ne conservant que les données au-dessus du coupé:

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

qui produit:

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