假设我有两个数据帧df1
和df2
:
df1 = structure(list(surname = c("Duisenberg", "Trichet", "Draghi"),
`start term` = structure(c(896659200, 1067644800, 1320105600
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), `end term` = structure(c(1067558400,
1320019200, 1572480000), class = c("POSIXct", "POSIXt"), tzone = "UTC")), row.names = c(1L,
9L, 15L), class = "data.frame") %>% data.frame(stringsAsFactors = F)
surname start.term end.term
1 Duisenberg 1998-06-01 2003-10-31
9 Trichet 2003-11-01 2011-10-31
15 Draghi 2011-11-01 2019-10-31
df2= data.frame(Date = c("2010-01-01","1997-01-01","2020-01-01","2004-01-01","2012-01-01","1999-01-01","2000-01-01","2020-01-01","2022-01-01","1996-01-01"), speaker = c("Mario Draghi","W.L. Duisenberg","Ciao","Jean-Claude Trichet","M. Draghi","W.L. Duisenberg","Jean-Claude Trichet","Bye","Ciao","Mario Draghi"), stringsAsFactors = F)
Date speaker
1 2010-01-01 Mario Draghi
2 1997-01-01 W.L. Duisenberg
3 2020-01-01 Ciao
4 2004-01-01 Jean-Claude Trichet
5 2012-01-01 M. Draghi
6 1999-01-01 W.L. Duisenberg
7 2000-01-01 Jean-Claude Trichet
8 2020-01-01 Bye
9 2022-01-01 Ciao
10 1996-01-01 Mario Draghi
当df1
中的名称出现在df2
中时,我可以很容易地找到:
which(grepl(paste0(df1$surname, collapse = "|"), df2$speaker, ignore.case = TRUE))
[1] 1 2 4 5 6 7 10
相反,更棘手的是:只有当df2
中的日期超出df1
(start.term
和end.term
(的边界时,df1
中的名称才会出现在df2
中。
结果应该是:
[1] 1 2 10
我该怎么做?有人能帮我吗?
谢谢!
我认为本质上您希望在这里对匹配的名称执行联接操作。因此,第一步是找出它们是什么:
library(dplyr)
surnames_regex <- paste0(df1$surname, collapse = "|")
df2$matching_name <- strsplit(df2$speaker, split = "\s") |>
lapply(
(name) {
matching_name <- grep(surnames_regex, name, v = T)
matching_name <- ifelse(
length(matching_name) > 0,
matching_name[1],
NA_character_
)
matching_name
}
) |>
unlist()
df2
# Date speaker matching_name
# 1 2010-01-01 Mario Draghi Draghi
# 2 1997-01-01 W.L. Duisenberg Duisenberg
# 3 2020-01-01 Ciao <NA>
# 4 2004-01-01 Jean-Claude Trichet Trichet
# 5 2012-01-01 M. Draghi Draghi
# 6 1999-01-01 W.L. Duisenberg Duisenberg
# 7 2000-01-01 Jean-Claude Trichet Trichet
# 8 2020-01-01 Bye <NA>
# 9 2022-01-01 Ciao <NA>
# 10 1996-01-01 Mario Draghi Draghi
然后,这只是一个加入这些名称并根据您定义的条件进行过滤的例子:
df2 |>
inner_join(
df1,
by = c("matching_name" = "surname")
) |>
filter(
Date < start.term |
Date > end.term
)
# Date speaker matching_name start.term end.term
# 1 2010-01-01 Mario Draghi Draghi 2011-11-01 2019-10-31
# 2 1997-01-01 W.L. Duisenberg Duisenberg 1998-06-01 2003-10-31
# 3 2000-01-01 Jean-Claude Trichet Trichet 2003-11-01 2011-10-31
# 4 1996-01-01 Mario Draghi Draghi 2011-11-01 2019-10-31
确保所有日期的格式一致,即使所有日期都属于Date类。然后这可以在一个SQL语句中完成。
library(sqldf)
df1a <- transform(df1, start.term = as.Date(start.term),
end.term = as.Date(end.term))
df2a <- transform(df2, Date = as.Date(Date))
sqldf("select distinct b.rowid, *
from df1a a
join df2a b on
(b.Date < a.[start.term] or b.Date > a.[end.term]) and
b.speaker like '%' || a.surname || '%'")
给予:
rowid surname start.term end.term Date speaker
1 1 Draghi 2011-11-01 2019-10-31 2010-01-01 Mario Draghi
2 2 Duisenberg 1998-06-01 2003-10-31 1997-01-01 W.L. Duisenberg
3 7 Trichet 2003-11-01 2011-10-31 2000-01-01 Jean-Claude Trichet
4 10 Draghi 2011-11-01 2019-10-31 1996-01-01 Mario Draghi