我有一个数据帧,看起来像这样。
df <- data.frame (ptid = c(1,1,1,1, 1, 2,2,2,3,3,3, 3),
labid = c("CRE", "CRE", "CRE", "CRE", "CRE", "CRE", "CRE", "CRE", "CRE","CRE", "CRE", "CRE"),
age = c(50, 54, 50.7, 51.3, 51, 52, 35, 37, 46, 46.1, 46.1, 46.1))在相同的参与者(相同的ptid)中,我希望只保留年龄在2.0岁以内的行。
这就是我想要的结果:
result <- data.frame(ptid = c(1,1,2,2,3),
labid = c("CRE", "CRE", "CRE", "CRE", "CRE"),
age = c(50,54,52,35,46))提前感谢您的帮助!我真的很纠结于这个问题!
发布于 2021-05-13 10:06:39
我们可以做一个arrange并在filter中使用diff
library(dplyr)
df %>%
arrange(ptid, age) %>%
group_by(ptid) %>%
filter(c(first(age), diff(age)) > 2) %>%
ungroup-output
# A tibble: 5 x 3
# ptid labid age
# <dbl> <chr> <dbl>
#1 1 CRE 50
#2 1 CRE 54
#3 2 CRE 35
#4 2 CRE 52
#5 3 CRE 46发布于 2021-05-13 10:45:32
你可以这样做:
df %>%
group_by(ptid)%>%
arrange(ptid, age) %>%
mutate(grp = cumsum(cumsum(c(0, diff(age)))>2))%>%
group_by(ptid, grp)%>%
slice(1) %>%
ungroup()%>%
select(-grp)
# A tibble: 5 x 3
ptid labid age
<dbl> <chr> <dbl>
1 1 CRE 50
2 1 CRE 54
3 2 CRE 35
4 2 CRE 52
5 3 CRE 46发布于 2021-05-13 16:14:44
定义一个函数f,它要么将输入分成间隔并识别重复项,要么在失败时返回最小的元素。然后,在每个ptid级别上使用ave和一个否定!来应用!,其中通过将最大和最小cut的差值除以2来获得要age到的间隔数。
f <- function(x, ...) tryCatch(duplicated(cut(x, ...)), error=function(e) order(x) > 1)
res <- subset(df, !ave(age, ptid, FUN=function(x) f(x, diff(range(x)) / 2)))
res
# ptid labid age
# 1 1 CRE 50
# 2 1 CRE 54
# 6 2 CRE 52
# 7 2 CRE 35
# 9 3 CRE 46注意事项: 1.观察的顺序不会被混淆。2.如果有更多相同年龄的ptid-labid,该解决方案将删除重复的aka领带。(如果出于任何原因不需要这样做,请查看rank()而不是order()。)
https://stackoverflow.com/questions/67513009
复制相似问题