选择绝对差异最小的重复行观察

时间:2019-05-16 14:15:39

标签: r dataframe dplyr

我有一个像这样的数据框:

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,低于所有其他组合。

2 个答案:

答案 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。然后,仅返回完整的案例。