在dplyr中找到最接近x的值

时间:2016-11-28 00:28:49

标签: r dplyr

library(dplyr)
a <- data_frame(id = c("A","A","A","B","B","B"),
                b = c(1.2, 1.5, 1.8, 1.1, 1.6, 1.4))

现在,我想为id中的每个catergories检索最接近1.43的值。 我以为我可以用:

a %>% group_by(id) %>% nth(which.min(abs(.$b-1.43)))

但是dplyr声明

Error: Don't know how to generate default for object of class grouped_df/tbl_df/tbl/data.frame

4 个答案:

答案 0 :(得分:10)

which.min()返回数字(或逻辑)向量的(第一个)最小值或最大值的索引。如果有多个相等的值,则彼此接近1.43并且您想要保留所有这些内容,您可以使用filter()

a %>% group_by(id) %>% filter(abs(b - 1.43) == min(abs(b - 1.43)))

#Source: local data frame [2 x 2]
#Groups: id [2]

#     id     b
#  <chr> <dbl>
#1     A   1.5
#2     B   1.4

如果您更喜欢坚持使用nth()函数,并且每个组只有一个值,则可以将其包装在汇总函数中,以便将其应用于每个组,并且还可以根据到?nth(),您还需要将向量作为参数传递给函数:

a %>% group_by(id) %>% summarise(b = nth(b, which.min(abs(b-1.43))))

# A tibble: 2 × 2
#     id     b
#  <chr> <dbl>
#1     A   1.5
#2     B   1.4

答案 1 :(得分:4)

离你的不太远

a %>% group_by(id) %>% summarise(which.min(abs(b-1.43)))
# A tibble: 2 × 2
#      id `which.min(abs(b - 1.43))`
#   <chr>                      <int>
# 1     A                          2
# 2     B                          3

或者,如果您需要值,而不是索引:

a %>% group_by(id) %>% summarise(b[which.min(abs(b-1.43))])
# A tibble: 2 × 2
#      id `b[which.min(abs(b - 1.43))]`
#   <chr>                         <dbl>
# 1     A                           1.5
# 2     B                           1.4

答案 2 :(得分:4)

有几种方法可以做到这一点。

这是一个dplyr解决方案(使用this answer找到):

a %>%
    group_by(id) %>%
    slice(which.min(abs(b - 1.43)))

     id     b
  <chr> <dbl>
1     A   1.5
2     B   1.4

这是一个基本解决方案:

do.call('rbind', by(a, a$id, function(x) x[which.min(abs(x$b - 1.43)), ]))

     id     b
  <chr> <dbl>
1     A   1.5
2     B   1.4

这是一个hacky dplyr解决方案:

a %>%
    mutate(AbsDiff = abs(b - 1.43)) %>%
    group_by(id) %>%
    mutate(AbsDiff_r = rank(AbsDiff, ties.method = 'first')) %>%
    filter(AbsDiff_r == 1)

     id     b AbsDiff AbsDiff_r
  <chr> <dbl>   <dbl>     <int>
1     A   1.5    0.07         1
2     B   1.4    0.03         1

答案 3 :(得分:2)

以下是data.table

的版本
library(data.table)
setDT(a)[, .(b= b[which.min(abs(b-1.43))]) , id]
#  id   b
#1:  A 1.5
#2:  B 1.4