0
votes

Nombre accumulé pour chaque élément d'une plage

J'ai une table x, où le début et la fin sont l'heure de la journée.

x = data.table (start = c (5,7,9,12), end = c (12, 14,15,20), val = 7:10)

Je veux que la table de sortie soit:

pour chaque heure de l'heure 4 (pas 5) à le 21 (et non le 20), a la valeur accumulée telle que:

hour total
4    0
5    7
6    7
7    15(7+8)


1 commentaires

Je ne comprends ni votre question ni votre exemple.


3 Réponses :


1
votes

Ma compréhension de la question OP est que chaque ligne de l'ensemble de données d'entrée x est un segment avec un début et une fin. Nous devons calculer pour chaque valeur de l'intervalle total la somme des valeurs correspondant aux segments dans lesquels l'heure est incluse.

Une solution possible avec dplyr / purrr :

# A tibble: 16 x 2
    hour total
   <int> <dbl>
 1     5     7
 2     6     7
 3     7    15
 4     8    15
 5     9    24
 6    10    24
 7    11    24
 8    12    34
 9    13    27
10    14    27
11    15    19
12    16    10
13    17    10
14    18    10
15    19    10
16    20    10

Le résultat est:

library(dplyr)
## Create the data 
x = data.frame(start=c(5,7,9,12), end=c(12,14,15,20), val = as.double(7:10))
## Extract possible values
values <- seq(from=min(x$start), to=max(x$end))
## Function for one given hour
cumval <- function(hour){
    tibble(
        hour=hour, 
        total = x %>% mutate(tot=if_else( (hour>=start & hour<=end), val, 0)) %>% 
        pull(tot) %>% sum
        )
}
## Iterate
values %>% purrr::map_dfr(cumval)


0 commentaires

1
votes

Voici une solution de base R simple:

hour  <- min(x$start):max(x$end)
total <- sapply(hour, function(i) sum(x$val[x$start <= i & x$end >= i])))
data.frame(hour, total)
#>    hour total
#> 1     5     7
#> 2     6     7
#> 3     7    15
#> 4     8    15
#> 5     9    24
#> 6    10    24
#> 7    11    24
#> 8    12    34
#> 9    13    27
#> 10   14    27
#> 11   15    19
#> 12   16    10
#> 13   17    10
#> 14   18    10
#> 15   19    10
#> 16   20    10


1 commentaires

Plus simple que le mien!



1
votes

Voici une autre option data.table utilisant by = .EACHI pour chaque heure:

    start end V1
 1:     4   4  0
 2:     5   5  7
 3:     6   6  7
 4:     7   7 15
 5:     8   8 15
 6:     9   9 24
 7:    10  10 24
 8:    11  11 24
 9:    12  12 34
10:    13  13 27
11:    14  14 27
12:    15  15 19
13:    16  16 10
14:    17  17 10
15:    18  18 10
16:    19  19 10
17:    20  20 10
18:    21  21  0

sortie:

x[.(hr=max(0L, min(x)-1L):min(23L, max(end)+1L)),
    on=.(start<=hr, end>=hr), by=.EACHI, fcoalesce(sum(val), 0L)]


0 commentaires