Извлечь строки из фрейма данных, которые отсутствовали в определенные дни - PullRequest
1 голос
/ 28 мая 2020

У меня есть фрейм данных:

Date          Agent
2020-02-10    A
2020-02-11    A
2020-02-12    A
2020-02-13    A
2020-02-14    A
2020-02-10    B
2020-02-12    B
2020-02-10    C
2020-02-11    C
2020-02-14    C

Я хочу получить фрейм данных с той строкой, которая отсутствовала в определенные дни с 2020-02-10 по 2020-02-14. Итак, желаемый результат:

Agent  Days_absent
B      2020-02-11; 2020-02-13; 2020-02-14
C      2020-02-12; 2020-02-13 

или

Date          Agent
2020-02-11    B
2020-02-13    B
2020-02-14    B
2020-02-12    C
2020-02-13    C

Как я могу это сделать?

Ответы [ 5 ]

2 голосов
/ 28 мая 2020

Вот довольно простой способ использования reshape2::melt и dplyr:

library(dplyr)
library(reshape2)

melt(table(df$Date, df$Agent)) %>% 
  filter(value == 0) %>% 
  select(Date = Var1, Agent = Var2, -value)
#>         Date Agent
#> 1 2020-02-11     B
#> 2 2020-02-13     B
#> 3 2020-02-14     B
#> 4 2020-02-12     C
#> 5 2020-02-13     C


Data

df <- structure(list(Date = structure(c(18302, 18303, 18304, 18305, 
18306, 18302, 18304, 18302, 18303, 18306), class = "Date"), Agent = c("A", 
"A", "A", "A", "A", "B", "B", "C", "C", "C")), row.names = c(NA, 
-10L), class = "data.frame")
0 голосов
/ 28 мая 2020

Немного поздно на вечеринку. Этот однострочник в Base-R

lapply(split(df,df$Agent), function(x) paste0(unique(df$Date)[!unique(df$Date) %in% x$Date], collapse="; "))

дает

$A
[1] ""

$B
[1] "2020-02-11; 2020-02-13; 2020-02-14"

$C
[1] "2020-02-12; 2020-02-13"
0 голосов
/ 28 мая 2020

A dplyr решение:

     df %>% 
   group_by(Agent) %>% 
   group_modify(~data.frame(setdiff(df$Date,.$Date))) %>% 
  rename(Date=2)
# A tibble: 5 x 2
# Groups:   Agent [2]
  Agent Date      
  <chr> <chr>     
1 B     2020-02-11
2 B     2020-02-13
3 B     2020-02-14
4 C     2020-02-12
5 C     2020-02-13

Данные

df<- structure(list(Date = c("2020-02-10", "2020-02-11", "2020-02-12", 
"2020-02-13", "2020-02-14", "2020-02-10", "2020-02-12", "2020-02-10", 
"2020-02-11", "2020-02-14"), Agent = c("A", "A", "A", "A", "A", 
"B", "B", "C", "C", "C")), class = "data.frame", row.names = c(NA, 
-10L))
0 голосов
/ 28 мая 2020

Вот еще одно решение, основанное на последовательности, которая выявляет пробелы, в которых не существует комбинации дата / агент, или даже допускает произвольный диапазон. Не уверен, что это то, что нужно OP.

cbind.data.frame(Date = seq(min(df$Date), max(df$Date),1), stringsAsFactors=F) %>% 
  crossing(cbind.data.frame(Agent = c("A", "B", "C"), stringsAsFactors=F)) %>% 
  left_join(df %>% mutate(actual = 1), by = c("Date", "Agent")) %>% 
  filter(is.na(actual)) %>% 
  select(-actual)
0 голосов
/ 28 мая 2020

Решение, использующее анти-соединение:

library(tidyverse)
#Data
df <- structure(list(Date = structure(c(18302, 18303, 18304, 18305, 
18306, 18302, 18304, 18302, 18303, 18306), class = "Date"), Agent = c("A", 
"A", "A", "A", "A", "B", "B", "C", "C", "C")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -10L)) %>% 
  mutate(Date = as.Date(Date))


dates <- tibble(Date = seq(as.Date("2020-02-10"), as.Date("2020-02-14"), "days")) %>% 
  expand_grid(Agent = c("A","B","C"))

dates %>% 
  anti_join(df) %>% 
  arrange(Agent)

# A tibble: 5 x 2
#  Date       Agent
#  <date>     <chr>
#1 2020-02-11 B    
#2 2020-02-13 B    
#3 2020-02-14 B    
#4 2020-02-12 C    
#5 2020-02-13 C 
...