Dúvida com manipulação

Olá!

Tenho uma estrutura de dados parecida com esta:

# A tibble: 5 x 4
  group  task start end  
  <chr> <dbl> <chr> <chr>
1 a         1 01:00 01:30
2 a         2 02:00 02:25
3 b         3 01:05 01:40
4 b         4 01:50 02:30
5 a         5 03:00 03:30

E desejo um output similar a este:

# A tibble: 5 x 7
  group last_task last_end next_task next_start next_end interval
  <chr>     <dbl> <chr>        <dbl> <chr>      <chr>    <chr>   
1 a            NA NA               1 01:00      01:30    NA      
2 a             1 01:30            2 02:00      02:25    00:30   
3 b            NA NA               3 01:05      01:40    NA      
4 b             3 01:40            4 01:50      02:30    00:10   
5 a             2 02:25            5 03:00      03:30    00:35  

De modo que cada linha contenha as duplas tarefa anterior + próxima tarefa, mantendo os respectivos grupos.
O interesse é calcular o intervalo do término da última tarefa até o início da próxima, do mesmo grupo.

De maneira figurada, é uma “linha do tempo” onde:

A-B
B-C
C-D

No SQL isto é possível via vários joins condicionais na mesma tabela. No R não obtive o mesmo resultado.

Podem ajudar, por favor?

Eu faria assim, usando lag e a função hm() pra transformar character em Period e ser possível fazer conta com datas.

library(tidyverse)
library(lubridate)

dados <- tribble(
  ~group, ~task,  ~start,    ~end,
  "a",      "1", "01:00", "01:30",
  "a",      "2", "02:00", "02:25",
  "b",      "3", "01:05", "01:40",
  "b",      "4", "01:50", "02:30",
  "a",      "5", "03:00", "03:30"
) 

dados %>%
  rename(
    next_start = start,
    next_end = end,
    next_task = task
  ) %>%
  group_by(group) %>%
  mutate(
    last_task = lag(next_task),
    last_end = lag(next_end),
    interval = as_datetime(hm(next_start) - hm(last_end)) %>% format(format = "%H:%M")
  )

Output:

#> # A tibble: 5 x 7
#> # Groups:   group [2]
#>   group next_task next_start next_end last_task last_end interval
#>   <chr> <chr>     <chr>      <chr>    <chr>     <chr>    <chr>   
#> 1 a     1         01:00      01:30    <NA>      <NA>     <NA>    
#> 2 a     2         02:00      02:25    1         01:30    00:30   
#> 3 b     3         01:05      01:40    <NA>      <NA>     <NA>    
#> 4 b     4         01:50      02:30    3         01:40    00:10   
#> 5 a     5         03:00      03:30    2         02:25    00:35

Created on 2020-05-22 by the reprex package (v0.3.0)

1 curtida

Show, @Athos
Com lag e lead eu consegui fazer. A lógica dessa função é simplesmente buscar a linha seguinte/anterior para um determinado grupo (portanto o arrange), ou ele faz um avaliação mais específica do dado maior/menor, mais antigo/mais novo?

@Guilherme! Não sei se entendi sua dúvida. Parece que é as duas coisas ao mesmo tempo. Para cada grupo (definido no group_by) o lead e o lag vai ser aplicado dentro de cada grupo (não vai ter troca de informação inter grupos). Sobre o arrange, ele serve para que o lead e o lag respeite a ordem temporal.
Se vc quiser o mais recente ou o mais antigo vc teria que usar as funções min e max. Mas se tiver ordenado vc pode usar as funções first, last, nth, lag, lead, etc.
Então ordenar é bem conveniente para essas operações!

Era isso?
abs!

1 curtida

Ficou claro @Athos, era isso mesmo. Valeu!