我有一个数据框df
:
id year groupid
1 A1 2000 G1
2 A1 2000 G1
3 A1 2000 G1
4 A2 2000 G2
5 A1 2001 G1
6 A12 2001 G1
7 A13 2001 G1
8 A3 2001 G2
9 A33 2001 G2
10 A4 2001 G3
11 A4 2002 G3
12 A5 2002 G3
13 A5 2003 G2
14 A6 2003 G4
我想要做的是在两个连续两年相同setdiff()
的值之间使用groupid
。
示例:
对于2000年,G1
有一个id
:A1
。对于20001年,G1
有三个不同的id
:A1
,A12
,A13
。因此,当在这两者之间应用setdiff()
时,它将返回2
。在2001年至2002年期间,由于2002年没有G1
,因此将给出0
的价值。对于相同的groupid
,如果两年不连续,则给定的值将是0
如果该组在第二年不存在或者是不同的id
。< / p>
预期结果:
year groupid newid
1 2000 G1 1
2 2000 G2 1
3 2000 G3 0
4 2000 G4 0
5 2001 G1 2
6 2001 G2 2
7 2001 G3 1
8 2001 G4 0
9 2002 G1 0
10 2002 G2 0
11 2002 G3 2
12 2002 G4 0
13 2003 G1 0
14 2003 G2 1
15 2003 G3 0
16 2003 G4 1
我使用for loop
,一些if()
和dplyr
函数完成了此操作,但由于我有很多行,所以需要花费太多时间(大约5分钟)。所以我正在寻找用一些dplyr
函数或data.table
函数替换循环,以便在更短的时间内完成此任务。
数据:
structure(list(id = c("A1", "A1", "A1", "A2", "A1", "A12", "A13",
"A3", "A33", "A4", "A4", "A5", "A5", "A6"), year = c(2000, 2000,
2000, 2000, 2001, 2001, 2001, 2001, 2001, 2001, 2002, 2002, 2003,
2003), groupid = c("G1", "G1", "G1", "G2", "G1", "G1", "G1",
"G2", "G2", "G3", "G3", "G3", "G2", "G4")), .Names = c("id",
"year", "groupid"), row.names = c(NA, -14L), class = "data.frame")
编辑:修改了示例
答案 0 :(得分:3)
此解决方案是我使用基座R tidyr
使用dplyr
和@jogo
以及aggregate(drop = FALSE)
(现已删除)答案的初始解决方案的组合:
df <- read.table(header = T, stringsAsFactors = F, text =
" id year groupid
1 A1 2000 G1
2 A1 2000 G1
3 A1 2000 G1
4 A2 2000 G2
5 A1 2001 G1
6 A12 2001 G1
7 A13 2001 G1
8 A3 2001 G2
9 A33 2001 G2
10 A4 2001 G3
11 A4 2002 G3
12 A5 2002 G3
13 A5 2003 G2
14 A6 2003 G4")
library(dplyr)
df %>%
aggregate(id ~ year + groupid, ., unique, drop = FALSE) %>%
group_by(groupid) %>%
arrange(year) %>%
mutate(new_ids = mapply(setdiff, id, lag(id)),
newid = lapply(new_ids, length)) %>%
ungroup() %>%
arrange(year, groupid) %>%
as.data.frame()
# year groupid id new_ids newid
# 1 2000 G1 A1 A1 1
# 2 2000 G2 A2 A2 1
# 3 2000 G3 0
# 4 2000 G4 0
# 5 2001 G1 A1, A12, A13 A12, A13 2
# 6 2001 G2 A3, A33 A3, A33 2
# 7 2001 G3 A4 A4 1
# 8 2001 G4 0
# 9 2002 G1 0
# 10 2002 G2 0
# 11 2002 G3 A4, A5 A5 1
# 12 2002 G4 0
# 13 2003 G1 0
# 14 2003 G2 A5 A5 1
# 15 2003 G3 0
# 16 2003 G4 A6 A6 1
编辑:解释,回答评论:
, .,
部分是df
应该是aggregate()
的第二个参数,而不是第一个(参见help("%>%")
)。但实际上它是为了缩短它,你最好使用更长,更健壮的形式和命名参数,例如:aggregate(formula = id ~ year + groupid, data = ., FUN = unique, drop = FALSE)
。
添加group_by()
是使lag()
一致使用所必需的。如果没有群组,我们会承担将2000, G2
的ID与2003, G1
的ID(aggregate()
之后的连续行)进行比较的风险。我们真正想要的是setdiff(..., lag(...
在groupid
组内发生,行按year
排序(因此可能不需要arrange(year)
)。缺少此group_by()
对此示例没有任何影响,但可能会在您的真实数据中生成一个。