[英]Conditional selection of repeated measures from data frame
我有数据,在可变数量的时间点对每个主题(id)进行重复测量。 我想为每个主题保留两行,时间点== 0和最接近4的时间点。在两个候选时间点距离4等距离的情况下,例如(3,5),我想选择最低的(3) )。
如下图中的“选择”列所示,不会保留带有“x”的行。
dat <- structure(list(id = c(172507L, 172507L, 172507L, 172525L, 172525L,
172525L, 172526L, 172526L, 172526L, 172527L, 172527L, 172527L,
172527L, 172527L), timepoint = c(0L, 2L, 6L, 0L, 4L, 5L, 0L,
5L, 2L, 2L, 3L, 5L, 6L, 0L)), class = "data.frame", row.names = c(NA,
-14L))
我们可以通过id
和timepoint
进行arrange
,并且对于每个组,当timepoint == 0
时选择第一个出现,并且在4 - timepoint
之间选择最小绝对值。 因为我们已经按timepoint
安排了它which.min
将选择具有较低值的第一个timepoint
(如果是平局)。
library(dplyr)
dat %>%
arrange(id, timepoint) %>%
group_by(id) %>%
slice(c(which.max(timepoint == 0), which.min(abs(4- timepoint))))
# id timepoint
# <int> <int>
#1 172507 0
#2 172507 2
#3 172525 0
#4 172525 4
#5 172526 0
#6 172526 5
#7 172527 0
#8 172527 3
你能做这样的事吗? 按距离排列然后按时间点排列最小的最接近的值。 然后,您可以使用first()
函数获取第一个值,或者在时间点为零时过滤。
library(tidyverse)
dat %>%
mutate(dist = abs(4-timepoint)) %>%
arrange(id, dist, timepoint) %>%
group_by(id) %>%
filter(timepoint %in% c(0, first(timepoint))) %>%
ungroup() %>%
arrange(id, timepoint)
这是data.table
解决方案。 它依赖于每个ID的时间点为0的假设。否则,您应该使用which.max(timepoint == 0)
。 感谢Ronak Shah的which.min方法。
编辑:更改为match(TRUE, timepoint == 0)
并修复了基本R方法中的问题。
library(data.table)
dt <- as.data.table(dat)
dt[order(timepoint),
.SD[c(match(TRUE, timepoint == 0), which.min(abs(4- timepoint)))],
by = id]
对于踢球,这里是基地R:
do.call(rbind, by(dat[order(dat$timepoint), ], dat[order(dat$timepoint), ], function(x) x[c(match(TRUE, x$timepoint == 0), which.min(abs(4-x$timepoint))),]) )
这样的事情应该有效:
zeros <-
dat %>%
filter(timepoint == 0) %>%
transmute(id, timepoint)
nonzeros <-
dat %>%
filter(timepoint != 0) %>%
mutate(diff = abs(timepoint - 4)) %>%
group_by(id) %>%
filter(diff == min(diff)) %>%
arrange(timepoint) %>%
slice(1) %>%
ungroup() %>%
transmute(id, timepoint)
df <-
bind_rows(zeros, nonzeros) %>%
arrange(id, timepoint)
可能有一种方法可以在一个管道中执行此操作,但我可以更轻松地直观地查看这种情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.