基于另一data.frame中的唯一标识符对data.frame进行子集化

时间:2017-01-25 11:27:39

标签: r dataframe subset

让我们说我们必须使用data.frames:

x <- data.frame(date=c(1,2,3,1,3),  id=c("a", "a", "a", "b", "b"), sum=50:54)
y <- data.frame(date=c(1,2,1,3), id=c("a", "a", "b", "b"))

x
  date id sum
1    1  a  50
2    2  a  51
3    3  a  52
4    1  b  53
5    3  b  54
y

  date id
1    1  a
2    2  a
3    1  b
4    3  b

现在,我想在x中找到日期不在y中的行,在同一个id中。在y中,我们在id a中有1,2和3,在y中我们在id a中只有1和2。 我如何识别(并且最好从x中删除)x中的第3行?

编辑:我找到了一个(非常难看和缓慢)的解决方案,但必须有更好更快的解决方案吗?目前我在两个大型data.frames上运行它,并且第一次花了一个多小时。我需要多次运行它,所以任何帮助都会受到赞赏。

z <- data.frame()

for (f in 1:length(unique(x$id))) {  #Run the iteration for all the unique id's in x
  id <- unique(x$id)[f]   #find the name of the id in this iteriation
  a <- x[x$id==id,]       #subset x 
  b <- y[y$id==id,]       #subset y
x.new <- a[a$date%in%unique(b$date),] #find the dates that are in x and also in y
z <- rbind(z, x.new)       #bind the two data.frames together
}

1 个答案:

答案 0 :(得分:2)

您似乎想要内部联接。您将问题概念化为&#34;在X中找到不在Y中的行,然后从X中删除它们,&#34; - 这通常被称为&#34 ;只保留X中也在Y中的行。&#34;

有很多方法可以做到这一点,它是base::merge

的默认设置
merge(x, y, all = F)
#   date id sum
# 1    1  a  50
# 2    1  b  53
# 3    2  a  51
# 4    3  b  54

R-FAQ .get

详细介绍了许多其他选项

如果您确实需要为其他目的识别已删除的行,dplyr::anti_join是一种方法。 anti_join(x, y)会返回x中不在y中的行。

library(dplyr)
anti_join(x, y)
# Joining, by = c("date", "id")
#   date id sum
# 1    3  a  52

如果速度是一个问题,data.table解决方法How to join (merge) data frames (inner, outer, left, right)?将是最快的。 as in this answer。但是,您的代码正在制定足够低效的步骤(在循环中增加数据框,重新计算相同的unique值,有时不必要)我的猜测是即使base::merge也会快几个数量级。