2016-03-22 2 views
3

У меня есть дата-рамка, где я хотел бы выбрать внутри каждой группы строки, где y является самым близким к определенному значению (например: 5).Подстановка по группе, ближайшей к определенному значению

set.seed(1234) 
df <- data.frame(x = c(rep("A", 4), 
         rep("B", 4)), 
       y = c(rep(4, 2), rep(1, 2), rep(6, 2), rep(3, 2)), 
       z = rnorm(8)) 

df 

## x y   z 
## 1 A 4 -1.2070657 
## 2 A 4 0.2774292 
## 3 A 1 1.0844412 
## 4 A 1 -2.3456977 
## 5 B 6 0.4291247 
## 6 B 6 0.5060559 
## 7 B 3 -0.5747400 
## 8 B 3 -0.5466319 

Результат будет выглядеть так:

## x y   z 
## 1 A 4 -1.2070657 
## 2 A 4 0.2774292 
## 3 B 6 0.4291247 
## 4 B 6 0.5060559 

Спасибо, Филипп

ответ

4
df %>% 
    group_by(x) %>% 
    mutate(
    delta = abs(y - 5) 
) %>% 
    filter(delta == min(delta)) %>% 
    select(-delta) 
+0

Работает должным образом, спасибо. –

0
val <- 5 
delta <- abs(val - df$y) 
df <- df[delta == min(delta), ] 
+0

вам не нужно указывать cols – Thierry

+1

добавьте это не будет использовать группировку на 'x' – Thierry

+0

Я указывал cols, потому что я не хотел, чтобы столбец diff включался в выходной кадр данных, поскольку он не является действительно должен быть частью этого. – cpander

3

В качестве альтернативы с использованием базы R:

df[do.call(c, tapply(df$y, df$x, function(x) x-5 == max(x - 5))),] 
    x y   z 
1 A 4 -1.2070657 
2 A 4 0.2774292 
5 B 6 0.4291247 
6 B 6 0.5060559 
1

Вот опция с data.table. Преобразуйте 'data.frame' в 'data.table' (setDT(df)), сгруппированные по 'x', мы создаем абсолютную разницу в 'y' с 5, проверяем для элементов, которые являются min от разницы, получают индекс строки (.I), извлеките столбец, который является индексом строки («V1»), и подмножество набора данных.

library(data.table) 
setDT(df)[df[, {v1 <- abs(y-5) 
       .I[v1==min(v1)]}, x]$V1] 
# x y   z 
#1: A 4 -1.2070657 
#2: A 4 0.2774292 
#3: B 6 0.4291247 
#4: B 6 0.5060559