Skip to content

Distinct & Duplicates

Two related questions: what are the unique values, and are there duplicate rows? The first is routine, how many genes, how many conditions. The second is a data-quality check: a file merged twice, a sample listed under two labels. dplyr uses distinct and n_distinct; Polars uses unique and n_unique.

Every code block runs in a container in the companion repository. One function differs between the two, noted below.

The unique values in a column, and a count of them.

distinct(expr, gene)
nrow(distinct(expr, condition)) # 2
n_distinct(expr$sample_id) # 8
gene
1 TP53
2 EGFR
3 MYC
4 BRCA1
5 GAPDH
6 ACTB
distinct conditions: 2
n_distinct sample_id: 8

Distinct works on combinations too. distinct(expr, gene, condition) gives 12 rows, the six genes times two conditions.

Here the first annotation row is duplicated, giving eight rows where seven are unique. This is where the two libraries differ in a way worth knowing.

with_dup <- bind_rows(annotation, annotation[1, ])
sum(duplicated(with_dup)) # 1: R flags only the repeat
nrow(with_dup) - nrow(distinct(with_dup)) # 1: rows removed
rows including the duplicate: 8
duplicated() flags: 1
rows removed by distinct(): 1

The trap: R’s duplicated() marks only the second and later copies of a row, so it reports 1, while Polars is_duplicated() marks every row that has a duplicate, both copies, so it reports 2. They are answering slightly different questions. To count how many rows a dedup removes, the safe formula in both is the number of rows minus the number of unique rows, which is 1 either way. distinct() and unique() themselves agree: both leave seven rows.