【问题标题】:Filter a Dataframe by Another Dataframe按另一个数据框过滤数据框
【发布时间】:2018-03-08 00:55:35
【问题描述】:

据说这个问题已经回答了。但是标记我的问题的用户未能测试解决方案,并且引用的问题不适用于我的问题。

我发现了有关如何使用另一个列表过滤数据框的问题,但我没有找到显示如何使用另一个数据框过滤数据框的内容。

我有两个数据框,第一个可以被认为是 ID 和日期的键。

   id       date
1 id1 2016-06-23
2 id2 2016-06-25
3 id3 2016-06-23
4 id4 2016-06-25
5 id5 2016-06-27

structure(list(id = structure(1:5, .Label = c("id1", "id2", "id3", 
"id4", "id5"), class = "factor"), date = structure(c(16975, 16977, 
16975, 16977, 16979), class = "Date")), .Names = c("id", "date"
), row.names = c(NA, -5L), class = "data.frame")

然后我有第二个带有 ID 和日期的数据框,我想过滤第二个数据框以仅返回第一行中 ID 的日期之后的行。

这是第二个数据框:

   id       date
1 id1 2016-06-20
2 id1 2016-06-23
3 id1 2016-06-24
4 id2 2016-06-23
5 id3 2016-06-27

structure(list(id = structure(c(1L, 1L, 1L, 2L, 3L), .Label = c("id1", 
"id2", "id3"), class = "factor"), date = structure(c(16972, 16975, 
16976, 16975, 16979), class = "Date")), .Names = c("id", "date"
), row.names = c(NA, -5L), class = "data.frame")

这就是结果的样子:

   id       date
1 id1 2016-06-24
2 id3 2016-06-27

【问题讨论】:

标签: r


【解决方案1】:

感谢上帝有dplyr。以下代码加入具有唯一标识符的df1,并仅保留与条件date >= date.1 匹配的这些行(filter)。

小心,因为默认情况下,当您在两个 data.frames 中具有相同的列名时,dplyr 将加入所有这些。然后我们必须指定by 参数并为变量名称添加后缀以区分相同的列名称。

library(dplyr)
library(magrittr)

df2 %>%
 left_join(df1, by = "id", suffix=c("",".2") ) %>%
 filter( date > date.2) %>%
 select( -date.2 )

#  id       date
# 1 id1 2016-06-23
# 2 id1 2016-06-24
# 3 id3 2016-06-27

【讨论】:

  • 此结果与 OP 的预期输出不同
  • >= 替换为 > 因为 OP 指定“之后”而不是“开启或之后”
【解决方案2】:

使用data.table的解决方案:

library(data.table)
setDT(d1)
setDT(d2)
merge(d1, d2, "id")[date.y > date.x, .(id, date = date.y)]

    id       date
1: id1 2016-06-24
2: id3 2016-06-27

【讨论】:

  • @C8H10N4O2 能给个链接吗?
  • 有一个示例 here 仅是有条件的(id 上没有 equi-join)。参见my answer below,例如两者都有。我仍然认为这个问题是一个骗局。
【解决方案3】:

data.table 中使用非等连接

library(data.table)

setDT(df1)
setDT(df2)

setnames(df1, 'date','date1') # disambiguate for conditional join

df1[df2, on=.(id, date1<date), nomatch=0]

返回:

  id      date1
1: id1 2016-06-24
2: id3 2016-06-27

在大型数据集上,我希望这种方法比任何使用 dplyr 和/或笛卡尔连接后跟过滤器的方法都要快。

【讨论】:

  • 为什么投反对票?这可能是提供的最有效的解决方案...
【解决方案4】:

所以你的第一个数据框基本上是一个索引。假设该索引称为 df1,而您要过滤的第二个数据帧是 df2,我将使用 dplyr 执行此操作:

library(dplyr)

df.result <- left_join(df2, df1, by = "id") %>% 
   filter(date.x > date.y) %>% 
   select(-date.y) 

eta:这将是结果:

   id     date.x
 1 id1 2016-06-24
 2 id3 2016-06-27

【讨论】:

  • 这是奇闻趣事的答案的副本
  • 好吧,在我发布我的之前我没有看到,但它不是完全重复的。我的更简单。
猜你喜欢
  • 2017-06-28
  • 2023-03-12
  • 2021-10-31
  • 2021-09-09
  • 2020-11-16
  • 2016-10-02
  • 2019-12-21
  • 2016-01-21
  • 1970-01-01
相关资源
最近更新 更多