与函数的逻辑比较不能返回所有组合
我想过滤从“ 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”。
第二个区块缺少鲍勃。
答案 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
对于连续的更改,我建议使用lead
或lag
。如果日期不是按顺序排列的,请先使用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
lead
和lag
正是我想要的。
我确认如果日期重复,lead
和lag
不起作用,我需要先按日期进行排列。
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"]))
完全适合我的目的。