Giới thiệu

Nhiều trường hợp chúng ta cần lọc ra những rows là các giá trị ranking thứ nth trong các nhóm.

Chọn giá trị nhỏ nhất, lớn nhất thì tương đối dễ dàng hơn chọn những giá trị có ranking thứ n bất kì (nth).

Chúng ta lấy dataset iris để minh họa

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages ------------------------------ tidyverse 1.3.1 --
v ggplot2 3.3.5     v purrr   0.3.4
v tibble  3.1.4     v dplyr   1.0.7
v tidyr   1.1.4     v stringr 1.4.0
v readr   2.0.2     v forcats 0.5.1
-- Conflicts --------------------------------- tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(data.table)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.14.2 using 4 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: ‘data.table’

The following objects are masked from ‘package:dplyr’:

    between, first, last

The following object is masked from ‘package:purrr’:

    transpose
data("iris")

Lọc min, max trong các nhóm

Chọn các row có giá trị Sepal.Length lớn nhất

iris.max <- setDT(iris)[, .SD[which.max(Sepal.Length)], by = Species]   # Max of groups

head(iris.max)

Chọn các row có giá trị Sepal.Length nhỏ nhất

iris.min <- setDT(iris)[, .SD[which.min(Sepal.Length)], by = Species]   # Min of groups

head(iris.min)

Lọc giá trị thứ n (nth)

Sử dụng dplyr. Sau khi sorting và ranking những rows trong các nhóm, chúng ta chọn rows thứ n = 10 trong mỗi nhóm.3 nhóm Species chọn ra 3 rows có rank = 10 như sau

iris.n <- iris       # Replicate example data
iris.n <- iris.n %>% arrange(Species, desc(Sepal.Length)) %>% 
  group_by(Species) %>%  
  mutate(numbering = row_number()) %>% # Create numbering variable
 filter(numbering == 10)
iris.n

Hoặc cách khác

library(dplyr)
iris.nth <- iris %>% arrange(Species, desc(Sepal.Length)) %>%
      group_by(Species) %>% 
      mutate(rank = sequence(rle(as.character(iris$Species))$lengths)) %>%
      filter(rank == 10)
  
head(iris.nth)
NA
LS0tDQp0aXRsZTogIlJhbmtpbmcgd2l0aGluIGdyb3VwcyAtIG50aCINCmF1dGhvcjogIlRoaWV1IE5ndXllbiINCmRhdGU6ICIxMC80LzIwMjEiDQpvdXRwdXQ6ICAgaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMjIEdp4bubaSB0aGnhu4d1DQoNCk5oaeG7gXUgdHLGsOG7nW5nIGjhu6NwIGNow7puZyB0YSBj4bqnbiBs4buNYyByYSBuaOG7r25nIHJvd3MgbMOgIGPDoWMgZ2nDoSB0cuG7iyByYW5raW5nIHRo4bupIG50aCB0cm9uZyBjw6FjIG5ow7NtLg0KDQpDaOG7jW4gZ2nDoSB0cuG7iyBuaOG7jyBuaOG6pXQsIGzhu5tuIG5o4bqldCB0aMOsIHTGsMahbmcgxJHhu5FpIGThu4UgZMOgbmcgaMahbiBjaOG7jW4gbmjhu69uZyBnacOhIHRy4buLIGPDsyByYW5raW5nIHRo4bupIG4gYuG6pXQga8OsIChudGgpLg0KDQpDaMO6bmcgdGEgbOG6pXkgZGF0YXNldCBpcmlzIMSR4buDIG1pbmggaOG7jWENCg0KYGBge3IgfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGRhdGEudGFibGUpDQoNCmRhdGEoImlyaXMiKQ0KYGBgDQoNCiMjIEzhu41jIG1pbiwgbWF4IHRyb25nIGPDoWMgbmjDs20NCg0KQ2jhu41uIGPDoWMgcm93IGPDsyBnacOhIHRy4buLIFNlcGFsLkxlbmd0aCBs4bubbiBuaOG6pXQNCg0KYGBge3IgfQ0KaXJpcy5tYXggPC0gc2V0RFQoaXJpcylbLCAuU0Rbd2hpY2gubWF4KFNlcGFsLkxlbmd0aCldLCBieSA9IFNwZWNpZXNdICAgIyBNYXggb2YgZ3JvdXBzDQoNCmhlYWQoaXJpcy5tYXgpDQpgYGANCg0KQ2jhu41uIGPDoWMgcm93IGPDsyBnacOhIHRy4buLIFNlcGFsLkxlbmd0aCBuaOG7jyBuaOG6pXQNCg0KYGBge3J9DQppcmlzLm1pbiA8LSBzZXREVChpcmlzKVssIC5TRFt3aGljaC5taW4oU2VwYWwuTGVuZ3RoKV0sIGJ5ID0gU3BlY2llc10gICAjIE1pbiBvZiBncm91cHMNCg0KaGVhZChpcmlzLm1pbikNCmBgYA0KDQojIyBM4buNYyBnacOhIHRy4buLIHRo4bupIG4gKG50aCkNCg0KU+G7rSBk4bulbmcgZHBseXIuDQpTYXUga2hpIHNvcnRpbmcgdsOgIHJhbmtpbmcgbmjhu69uZyByb3dzIHRyb25nIGPDoWMgbmjDs20sIGNow7puZyB0YSBjaOG7jW4gcm93cyB0aOG7qSBuID0gMTAgdHJvbmcgbeG7l2kgbmjDs20uMyBuaMOzbSBTcGVjaWVzIGNo4buNbiByYSAzIHJvd3MgY8OzIHJhbmsgPSAxMCBuaMawIHNhdQ0KDQpgYGB7cn0NCmlyaXMubiA8LSBpcmlzICAgICAgICMgUmVwbGljYXRlIGV4YW1wbGUgZGF0YQ0KaXJpcy5uIDwtIGlyaXMubiAlPiUgYXJyYW5nZShTcGVjaWVzLCBkZXNjKFNlcGFsLkxlbmd0aCkpICU+JSANCiAgZ3JvdXBfYnkoU3BlY2llcykgJT4lICANCiAgbXV0YXRlKG51bWJlcmluZyA9IHJvd19udW1iZXIoKSkgJT4lICMgQ3JlYXRlIG51bWJlcmluZyB2YXJpYWJsZQ0KIGZpbHRlcihudW1iZXJpbmcgPT0gMTApDQppcmlzLm4NCmBgYA0KSG/hurdjIGPDoWNoIGtow6FjDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KaXJpcy5udGggPC0gaXJpcyAlPiUgYXJyYW5nZShTcGVjaWVzLCBkZXNjKFNlcGFsLkxlbmd0aCkpICU+JQ0KICAgICAgZ3JvdXBfYnkoU3BlY2llcykgJT4lIA0KICAgICAgbXV0YXRlKHJhbmsgPSBzZXF1ZW5jZShybGUoYXMuY2hhcmFjdGVyKGlyaXMkU3BlY2llcykpJGxlbmd0aHMpKSAlPiUNCiAgICAgIGZpbHRlcihyYW5rID09IDEwKQ0KICANCmhlYWQoaXJpcy5udGgpDQoNCmBgYA0K