在dplyr中找到最接近x的值

Mis*_*sha 5 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))
Run Code Online (Sandbox Code Playgroud)

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

a %>% group_by(id) %>% nth(which.min(abs(.$b-1.43)))
Run Code Online (Sandbox Code Playgroud)

但是dplyr说

Error: Don't know how to generate default for object of class grouped_df/tbl_df/tbl/data.frame
Run Code Online (Sandbox Code Playgroud)

Psi*_*dom 11

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
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢坚持使用该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
Run Code Online (Sandbox Code Playgroud)


bou*_*all 9

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

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

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

     id     b
  <chr> <dbl>
1     A   1.5
2     B   1.4
Run Code Online (Sandbox Code Playgroud)

这是一个基本的解决方案:

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
Run Code Online (Sandbox Code Playgroud)

这是一个hackydplyr解决方案:

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
Run Code Online (Sandbox Code Playgroud)


dww*_*dww 5

离你所拥有的不远

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)