与任何经过dplyr过滤的数据进行逻辑比较

时间:2019-02-14 05:33:24

标签: r dplyr

与函数的逻辑比较不能返回所有组合

我想过滤从“ C”提高到“ A”且中间没有其他成绩的学生。我想保持列表开放,以便在列表中包含其他值。例如“ C”和“ D”到“ A”。日期可能并不总是连续的,有时还会重复。

我的第二个问题是为什么鲍勃从过滤器中丢失了。

library(dplyr)
library(lubridate)
name <- c(rep("adam",5), rep("bob",5), rep("charlie",5), rep("dave",5))
date <- lubridate::date(rep(seq.Date(as.Date("2015-01-01"),as.Date("2019-01-01"),"years"),4))
score <- c("C","B","A","C","A",
       "A","B","A","B","C",
       "C","A","B","A","C",
       "B","A","A","A","C")
df <- data.frame(name,date,score)

df %>%
  group_by(name) %>%
  filter(any(date[score %in% c("A")] > date[score %in% c("C")]))%>%
  filter(!any(date[score %in% c("B")] > date[score %in% c("C")] &
              date[score %in% c("B")] < date[score %in% c("A")]))

# Charlie...

df %>%
  group_by(name) %>%
  filter(any(date[score %in% c("B")] < date[score %in% c("A")])) %>%
  summarize
# 1 adam   
# 2 charlie
# 3 dave   

第一段应该包括亚当。得分依次为“ C”和“ A”。

第二个区块缺少鲍勃。

2 个答案:

答案 0 :(得分:1)

您的问题是<是成对比较的。使用第二个示例:

df %>%
  group_by(name) %>%
  filter(any(date[score %in% c("B")] < date[score %in% c("A")])) %>%
  summarize

## let's look at bob
# 6      bob 2015-01-01     A
# 7      bob 2016-01-01     B
# 8      bob 2017-01-01     A
# 9      bob 2018-01-01     B
# 10     bob 2019-01-01     C

## call this X
date[score %in% c("B")] # corresponds to two dates:
# 2016-01-01
# 2018-01-01

## and this Y
date[score %in% c("A")] # also two dates
# 2015-01-01
# 2017-01-01

X < Y ## returns FALSE FALSE
# because X[1] > Y[1] and X[2] > Y[2]

您可以通过以下方法解决此问题:

df %>%
  group_by(name) %>%
  # is the first B before the last A
  filter(min(date[score %in% "B"]) < max(date[score %in% "A"])) %>%
  summarize
#   name   
#   <fct>  
# 1 adam   
# 2 bob    
# 3 charlie
# 4 dave   

对于连续的更改,我建议使用leadlag。如果日期不是按顺序排列的,请先使用arrange将其按顺序排列:

df %>% group_by(name) %>%
  filter(any(score %in% c("A") & lead(score) %in% c("C"))) %>%
  summarize
#   name   
#   <fct>  
# 1 adam   
# 2 charlie
# 3 dave

但是,如果日期重复,此操作将无效。我想到重复日期的最简单方法是将它们折叠成一行,例如

df %>% group_by(name, date) %>%
  summarize(scores = paste(score, collapse = "")) %>%
  group_by(name) %>%
  filter(grepl("A", scores) & lead(grepl("C", scores)) %>% 
  summarize
# # A tibble: 3 x 1
#   name   
#   <fct>  
# 1 adam   
# 2 charlie
# 3 dave  

我没有对具有多个日期的数据进行测试,但是应该可以。

答案 1 :(得分:0)

感谢@Gregor

leadlag正是我想要的。 我确认如果日期重复,leadlag不起作用,我需要先按日期进行排列。 grepl能够解决重复日期的问题。 现在,我必须弄清楚如何弄清分数。 这是有兴趣的人的代码

name <- c(rep("adam",3), rep("bob",3), rep("charlie",3), rep("dave",3))
date <- lubridate::date(rep(c(as.Date("2014-01-01"),as.Date("2015-01-01"),as.Date("2015-01-01")),4))
score <- c("C","B","A",
           "C","A","B",
           "C","A","A",
           "C","B","B")
df <- data.frame(name,date,score)

df %>% group_by(name) %>%
  filter(any(score %in% c("C") & lead(score %in% c("A")))) %>%
  summarize

# A tibble: 2 x 1
#  name   
#  <fct>  
# 1 bob    
# 2 charlie

df %>% group_by(name, date) %>%
  summarize(scores = paste(score, collapse = "")) %>%
  group_by(name) %>%
  filter(any(grepl("C", scores) & lead(grepl("A", scores))))

# # A tibble: 6 x 3
# # Groups:   name [3]
# name    date       scores
# <fct>   <date>     <chr> 
#   1 adam    2014-01-01 C     
# 2 adam    2015-01-01 BA    
# 3 bob     2014-01-01 C     
# 4 bob     2015-01-01 AB    
# 5 charlie 2014-01-01 C     
# 6 charlie 2015-01-01 AA  

关于成对比较的第二个问题。

我得出的相同结论是,>没有进行成对比较。 当我研究为什么any函数不能按预期工作时,这个问题就暴露出来了。

1:3 > 2:4
FALSE FALSE FALSE

我认为expand.grid可以提供帮助,但是我需要了解有关函数式编程,purrr软件包的更多信息,并学习如何将它们结合在一起。

filter(min(date[score %in% "B"]) < max(date[score %in% "A"]))
完全适合我的目的。