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)
有几种方法可以做到这一点。
这是一个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)
离你所拥有的不远
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)