Select varying number of top_n for different groups using dplyr

Viewed 54

I have the following dataframe. I want to prefer dplyr to solve this problem. For each zone I want at minimum two values. Value > 4.0 is preferred.

Therefore, for zone 10 all values (being > 4.0) are kept. For zone 20, top two values are picked. Similarly for zone 30.

zone <- c(rep(10,4), rep(20, 4), rep(30, 4))
set.seed(1)
value <- c(4.5,4.3,4.6, 5,5, rep(3,7)) + round(rnorm(12, sd = 0.1),1)
df <- data.frame(zone, value)
> df
   zone value
1    10   4.4
2    10   4.3
3    10   4.5
4    10   5.2
5    20   5.0
6    20   2.9
7    20   3.0
8    20   3.1
9    30   3.1
10   30   3.0
11   30   3.2
12   30   3.0

The desired output is as follows

> df
   zone value
1    10   4.4
2    10   4.3
3    10   4.5
4    10   5.2
5    20   5.0
6    20   3.1
7    30   3.1
8    30   3.2

I thought of using top_n but it picks the same number for each zone.

2 Answers

You could dynamically calculate n in top_n

library(dplyr)  
df %>% group_by(zone) %>% top_n(max(sum(value > 4), 2), value)


#   zone value
#  <dbl> <dbl>
#1    10   4.4
#2    10   4.3
#3    10   4.5
#4    10   5.2
#5    20   5  
#6    20   3.1
#7    30   3.1
#8    30   3.2

can do so

library(tidyverse)
df %>% 
  group_by(zone) %>% 
  filter(row_number(-value) <=2 | head(value > 4))
Related