Filter dataset to not show top rows by a column

Viewed 70

This is probably a easier one. (Preferable tidyverse solution)

Two questions Q1. Why doesnt below give me top 4 rows by maximum Sepal.Length values

library(tidyverse)
1. iris %>% top_n(Sepal.Length,4)

Q2 I want to do the opposite of top_n, slice_max. I want to show the dataframe without the top n rows within a dataframe

library(tidyverse)
#something like below
iris %>% filter(!top_n(Sepal.Length,4))

The output for 1. should be 4 rows, the output of 2. should be 146 rows (150-4 rows by top Sepal.Length values without ties)

2 Answers

slice family of functions replaces the soon to be deprecated top_n. Specify the column to be ordered in order_by and n in slice_max

library(dplyr)
iris %>% 
      slice_max(order_by = Sepal.Length, n = 4)

By default, it uses with_ties = TRUE. If we need to remove the ties, specify it as FALSE


For the second case, setdiff (there is a data.frame method in dplyr) can be used

iris %>% 
  slice_max(order_by = Sepal.Length, n = 4) %>% 
  setdiff(iris, .)

Or another option is to create a ranking with dense_rank and filter based on the rank

iris %>%
     filter(!dense_rank(-Sepal.Length) %in% 1:4) 

If we want to only remove the 4 rows, then use row_number

iris %>%
    filter(!row_number(-Sepal.Length) %in% 1:4)

Or with slice

iris %>% 
    slice(setdiff(row_number(-Sepal.Length), 1:4))

The main reason your first approach is not working is because of the order or arguments to top_n. Consider:

args(top_n)
#function (x, n, wt) 
#NULL

Recall that the %>% operator passes the left hand side as the first argument of the right hand side. Therefore, Septal.Length becomes the second and 4 becomes the 3rd.

Thus, the column you want to use to filter on needs to be last or specifically defined:

iris %>%
   top_n(wt=Sepal.Length,4)
#  Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
#1          7.7         3.8          6.7         2.2 virginica
#2          7.7         2.6          6.9         2.3 virginica
#3          7.7         2.8          6.7         2.0 virginica
#4          7.9         3.8          6.4         2.0 virginica
#5          7.7         3.0          6.1         2.3 virginica

#Altenative
iris %>%
  top_n(4,Sepal.Length)

Please refer to @akrun's answer for your second question.

Related