我有一个像这样的数据框:
df <- data.frame(id = c(1,1,1,2,2,3,3,3,3),
vars = c(1,2,5, 1,3, 0,2,4,-1))
> df
id vars
1 1 1
2 1 2
3 1 5
4 2 1
5 2 3
6 3 0
7 3 2
8 3 4
9 3 -1
在此数据框中,每个id
可以具有多个观察值。
我现在想为每个id
选择对vars
的绝对差最小的那对(2个观察值)。
在上述情况下,
id vars
1 1 1
2 1 2
3 2 1
4 2 3
5 3 0
6 3 -1
对于id
1,值1和2具有最低的绝对差,
id
2仅具有2个观测值,因此两者均被自动选择。
对于id
3,选择的变量将为0和-1,因为绝对差为1,低于所有其他组合。
答案 0 :(得分:8)
您不需要进行所有比较(也可以让arrange
为您进行比较),因为一旦对值进行了排序,每个值就已经在其差值旁边最小化。
df %>%
group_by(id) %>%
arrange(vars) %>%
slice(which.min(diff(vars)) + 0:1)
# # A tibble: 6 x 2
# # Groups: id [3]
# id vars
# <dbl> <dbl>
# 1 1 1
# 2 1 2
# 3 2 1
# 4 2 3
# 5 3 -1
# 6 3 0
data.table版本
library(data.table)
setDT(df)
df[df[order(vars), .I[which.min(diff(vars)) + 0:1], id]$V1]
# id vars
# 1: 3 -1
# 2: 3 0
# 3: 1 1
# 4: 1 2
# 5: 2 1
# 6: 2 3
答案 1 :(得分:1)
不是最简洁,但是可以。也许有人可以改善这个想法。
df1%>%group_by(id)%>%mutate(vars2=which.min(abs(diff(combn(num(vars),2)))))%>%
mutate(vars1=ifelse(vars%in%combn(num(vars),2)[,vars2],vars,NA))%>%select(id,vars1)%>%.[complete.cases(.),]
# A tibble: 6 x 2
# Groups: id [3]
id vars1
<dbl> <dbl>
1 1 1
2 1 2
3 2 1
4 2 3
5 3 0
6 3 -1
主要思想是对每个组的值的所有可能组合进行区别。 vars2
使列的差异最小。如果该值是vars2
列中存在的两个值之一,则将其保留。否则,它设置为NA
。然后,仅返回完整的案例。