mutate: выбрал все строки кроме текущей в сгруппированном df (dplyr) - PullRequest
2 голосов
/ 05 февраля 2020

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

вот мой код:

library(tidyverse)
library(lubridate)


# data
df<- data.frame(times=c("01/01/2020","01/02/2020","01/07/2020","01/10/2020","01/01/2020","01/03/2020","01/05/2020","01/07/2020"))
starttime= mdy(df$times)


df <- tibble(team=c("A","A","A","A","B","B","B","B"),
             player=c(1,2,3,4,1,2,3,4),
             starttime= starttime,
             stoptime= starttime+days(1))


# find overlaps
df %>% 
  mutate(interval=lubridate::interval(starttime,stoptime)) %>% #calculate interval
  group_by(team) %>% 
  mutate(overlap_flag= case_when(
    sum(starttime %within% as.list(interval)) == 0 ~ 0, # I want to chose as.list(interval[except actual row])
    sum(starttime %within% as.list(interval)) > 0 ~ 1, # I want to chose as.list(interval[except actual row])
    TRUE ~ NA_real_))

дает мне:

# A tibble: 8 x 6
# Groups:   team [2]
  team  player starttime  stoptime   interval                       overlap_flag
  <chr>  <dbl> <date>     <date>     <Interval>                            <dbl>
1 A          1 2020-01-01 2020-01-02 2020-01-01 UTC--2020-01-02 UTC            1
2 A          2 2020-01-02 2020-01-03 2020-01-02 UTC--2020-01-03 UTC            1
3 A          3 2020-01-07 2020-01-08 2020-01-07 UTC--2020-01-08 UTC            1
4 A          4 2020-01-10 2020-01-11 2020-01-10 UTC--2020-01-11 UTC            1
5 B          1 2020-01-01 2020-01-02 2020-01-01 UTC--2020-01-02 UTC            1
6 B          2 2020-01-03 2020-01-04 2020-01-03 UTC--2020-01-04 UTC            1
7 B          3 2020-01-05 2020-01-06 2020-01-05 UTC--2020-01-06 UTC            1
8 B          4 2020-01-07 2020-01-08 2020-01-07 UTC--2020-01-08 UTC            1

я хочу получить:

# A tibble: 8 x 6
# Groups:   team [2]
  team  player starttime  stoptime   interval                       overlap_flag
  <chr>  <dbl> <date>     <date>     <Interval>                            <dbl>
1 A          1 2020-01-01 2020-01-02 2020-01-01 UTC--2020-01-02 UTC            1
2 A          2 2020-01-02 2020-01-03 2020-01-02 UTC--2020-01-03 UTC            1
3 A          3 2020-01-07 2020-01-08 2020-01-07 UTC--2020-01-08 UTC            0
4 A          4 2020-01-10 2020-01-11 2020-01-10 UTC--2020-01-11 UTC            0
5 B          1 2020-01-01 2020-01-02 2020-01-01 UTC--2020-01-02 UTC            0
6 B          2 2020-01-03 2020-01-04 2020-01-03 UTC--2020-01-04 UTC            0
7 B          3 2020-01-05 2020-01-06 2020-01-05 UTC--2020-01-06 UTC            0
8 B          4 2020-01-07 2020-01-08 2020-01-07 UTC--2020-01-08 UTC            0

Я знаю, что может быть решение data.table ... однако, мне интересно, легко ли это можно сделать с помощью dplyr

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

Не совсем точно, если вы можете исключить одну строку напрямую, однако, есть один способ использовать функцию purrr map. Также, глядя на ожидаемый результат, кажется, вы также хотите рассмотреть stoptime, чтобы определить overlap_flag.

library(dplyr)
library(lubridate)

df %>% 
  mutate(interval=interval(starttime,stoptime)) %>%
  group_by(team) %>% 
  mutate(overlap_flag = purrr::map_int(row_number(),
 ~+any(starttime[.x] %within% interval[-.x] | stoptime[.x] %within% interval[-.x])))


#  team  player starttime  stoptime   interval                       overlap_flag
#  <chr>  <dbl> <date>     <date>     <Interval>                            <int>
#1 A          1 2020-01-01 2020-01-02 2020-01-01 UTC--2020-01-02 UTC            1
#2 A          2 2020-01-02 2020-01-03 2020-01-02 UTC--2020-01-03 UTC            1
#3 A          3 2020-01-07 2020-01-08 2020-01-07 UTC--2020-01-08 UTC            0
#4 A          4 2020-01-10 2020-01-11 2020-01-10 UTC--2020-01-11 UTC            0
#5 B          1 2020-01-01 2020-01-02 2020-01-01 UTC--2020-01-02 UTC            0
#6 B          2 2020-01-03 2020-01-04 2020-01-03 UTC--2020-01-04 UTC            0
#7 B          3 2020-01-05 2020-01-06 2020-01-05 UTC--2020-01-06 UTC            0
#8 B          4 2020-01-07 2020-01-08 2020-01-07 UTC--2020-01-08 UTC            0
1 голос
/ 05 февраля 2020

Мы можем использовать row_number() до l oop над строками, а затем использовать это как индекс при удалении значения 'starttime'

library(dplyr)
library(lubridate)
library(purrr)
df %>% 
  mutate(interval = as.list(interval(starttime, stoptime))) %>% 
  group_by(team) %>%
  mutate(overlap_flag = +(map2_lgl(row_number(), 
        interval, ~ sum(starttime[-.x] %within% .y) > 0)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...