比较分组数据框中的组

Cru*_*dle 5 grouping compare r sequential dplyr

我正在尝试对数据框中后续组中的项目进行比较-我想当您知道自己在做什么时,这很容易...

我的数据集可以表示如下:

set.seed(1)
data <- data.frame(
 date = c(rep('2015-02-01',15), rep('2015-02-02',16), rep('2015-02-03',15)),
 id = as.character(c(1005 + sample.int(10,15,replace=TRUE), 1005 + sample.int(10,16,replace=TRUE), 1005 + sample.int(10,15,replace=TRUE)))
)
Run Code Online (Sandbox Code Playgroud)

这会产生一个如下所示的数据框:

date    id
1/02/2015   1008
1/02/2015   1009
1/02/2015   1011
1/02/2015   1015
1/02/2015   1008
1/02/2015   1014
1/02/2015   1015
1/02/2015   1012
1/02/2015   1012
1/02/2015   1006
1/02/2015   1008
1/02/2015   1007
1/02/2015   1012
1/02/2015   1009
1/02/2015   1013
2/02/2015   1010
2/02/2015   1013
2/02/2015   1015
2/02/2015   1009
2/02/2015   1013
2/02/2015   1015
2/02/2015   1008
2/02/2015   1012
2/02/2015   1007
2/02/2015   1008
2/02/2015   1009
2/02/2015   1006
2/02/2015   1009
2/02/2015   1014
2/02/2015   1009
2/02/2015   1010
3/02/2015   1011
3/02/2015   1010
3/02/2015   1007
3/02/2015   1014
3/02/2015   1012
3/02/2015   1013
3/02/2015   1007
3/02/2015   1013
3/02/2015   1010
Run Code Online (Sandbox Code Playgroud)

然后我想按日期(group_by)对数据进行分组,然后在组之间进行比较之前过滤掉重复的(不同的)。我想要做的是每天确定添加哪些新 id 以及离开哪些 id。因此,将比较第 1 天和第 2 天以确定第 2 天不在第 1 天的 ID 和第 1 天但不存在于第 2 天的 ID,然后在第 2 天和第 3 天等之间进行相同的比较。
使用 anti_join (dplyr) 可以很容易地进行比较,但我不知道如何引用数据集中的各个组。

我的尝试(或我的尝试之一)看起来像:

data %>%
  group_by(date) %>%
  distinct(id) %>%
  do(lost = anti_join(., lag(.), by="id"))
Run Code Online (Sandbox Code Playgroud)

但当然这不起作用,我只是得到:

Error in anti_join_impl(x, y, by$x, by$y) : Can't join on 'id' x 'id' because of incompatible types (factor / logical)
Run Code Online (Sandbox Code Playgroud)

我正在尝试做的事情是可能的,还是应该考虑编写一个笨拙的函数来做到这一点?

Cru*_*dle 3

我确信我不会投票给自己的答案,但我必须说我最喜欢我的答案。我希望得到一个使用 dplyr 工具来解决问题的答案,所以我继续研究,我想我现在有了一个(半)优雅的解决方案(除了我函数中的 for 循环)。

\n\n

以相同的方式生成示例数据集,但使用更多数据使其更有趣:

\n\n
set.seed(1)\ndata <- data.frame(\n  date = c(rep(\'2015-02-01\',15), rep(\'2015-02-02\',16), rep(\'2015-02-03\',15), rep(\'2015-02-04\',15), rep(\'2015-02-05\',15)),\n  id = as.character(c(1005 + sample.int(10,15,replace=TRUE), 1005 + sample.int(10,16,replace=TRUE), 1005 + sample.int(10,15,replace=TRUE), 1005 + sample.int(10,15,replace=TRUE), 1005 + sample.int(10,15,replace=TRUE)))\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n

通过互联网搜索,我发现了 dplyr 函数“nest()”,它看起来可以解决我所有的分组问题。Nest() 函数获取由 group_by() 创建的组,并将它们滚动到数据框列表中,这样您最终会为分组的每个变量提供一个条目,然后为适合的所有剩余变量提供一个数据框该组 - 这里是:

\n\n
dataNested <- data %>%\n  group_by(date) %>%\n  distinct(id) %>%\n  nest()\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会产生一个相当奇怪的数据框,如下所示:

\n\n
     date          data\n1    2015-02-01    list(id = c(3, 4, 6, 10, 9, 7, 1, 2, 8))\n2    2015-02-02    list(id = c(5, 8, 10, 4, 3, 7, 2, 1, 9))\n3    2015-02-03    list(id = c(6, 5, 2, 9, 7, 8))\n4    2015-02-04    list(id = c(1, 5, 8, 7, 9, 3, 4, 6, 10))\n5    2015-02-05    list(id = c(3, 5, 4, 7, 8, 1, 9))\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中列表中的索引引用了 id 列表(奇怪但正确)。

\n\n

现在,我们可以通过索引号引用组,即:

\n\n
dataNested$data[[2]]\n
Run Code Online (Sandbox Code Playgroud)\n\n

返回:

\n\n
# A tibble: 9 \xc3\x97 1\n      id\n  <fctr>\n1   1010\n2   1013\n3   1015\n4   1009\n5   1008\n6   1012\n7   1007\n8   1006\n
Run Code Online (Sandbox Code Playgroud)\n\n

从这里开始,编写一个函数来执行 anti_join 是一个简单的问题,这样我们就可以得到每个后续组之间的差异(尽管这是我并不自豪的部分,并且真正开始显示出我对 R 的缺乏)技能 - 请随时提出改进建议):

\n\n
## Function departed() - returns the id\'s that were dropped from each subsequent time period\ndeparted <- function(groups) {\n  tempList <- vector("list", nrow(groups))\n  # Loop through the groups and do an anti_join between each\n  for (i in seq(1, nrow(groups) - 1)) {\n  tempList[[i + 1]] <-\n  anti_join(data.frame(groups$data[[i]]),  data.frame(groups$data[[i + 1]]), by = "id")\n\n  }\n  return(tempList)\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

将此函数应用于我们的嵌套数据会生成已离开 id 的列表:

\n\n
> departedIDs <- dataNested %>% departed()\n\n> departedIDs\n[[1]]\nNULL\n\n[[2]]\n    id\n1 1011\n\n[[3]]\n    id\n1 1006\n2 1008\n3 1009\n4 1015\n\n[[4]]\n    id\n1 1007\n\n[[5]]\n    id\n1 1011\n2 1015\n
Run Code Online (Sandbox Code Playgroud)\n\n

我希望这个答案能够帮助其他与我的大脑工作方式相同的人。

\n