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)
我正在尝试做的事情是可能的,还是应该考虑编写一个笨拙的函数来做到这一点?
我确信我不会投票给自己的答案,但我必须说我最喜欢我的答案。我希望得到一个使用 dplyr 工具来解决问题的答案,所以我继续研究,我想我现在有了一个(半)优雅的解决方案(除了我函数中的 for 循环)。
\n\n以相同的方式生成示例数据集,但使用更多数据使其更有趣:
\n\nset.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)\nRun Code Online (Sandbox Code Playgroud)\n\n通过互联网搜索,我发现了 dplyr 函数“nest()”,它看起来可以解决我所有的分组问题。Nest() 函数获取由 group_by() 创建的组,并将它们滚动到数据框列表中,这样您最终会为分组的每个变量提供一个条目,然后为适合的所有剩余变量提供一个数据框该组 - 这里是:
\n\ndataNested <- data %>%\n group_by(date) %>%\n distinct(id) %>%\n nest()\nRun 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))\nRun Code Online (Sandbox Code Playgroud)\n\n其中列表中的索引引用了 id 列表(奇怪但正确)。
\n\n现在,我们可以通过索引号引用组,即:
\n\ndataNested$data[[2]]\nRun 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\nRun 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}\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n\n我希望这个答案能够帮助其他与我的大脑工作方式相同的人。
\n| 归档时间: |
|
| 查看次数: |
869 次 |
| 最近记录: |