Широко известную в узких кругах базу UNIPROT можно скачать для локального использования в виде очень простых по своей структуре, но не очень удобных в использовании файлов. Например, goa_uniprot_gcrp.gpa.gz (contains all GO annotations for canonical accessions from the UniProt reference proteomes for all species, which provide one protein per gene. The reference proteomes comprise the protein sequences annotated in Swiss-Prot or the longest TrEMBL transcript if there is no Swiss-Prot record) содержит несколько строк комментариев, начинающихся с "!", за которыми следует таблица из 12 столбцов и 400 млн. строк без заголовков. В разархивированном виде файл весит 44 Гб, и для нормальной работы с ним в традиционном R-стиле с загрузкой таблицы целиком в ОЗУ нужно иметь в запасе ~128 Гб. Под катом решение в несколько строк кода, позволяющее снизить требования по памяти до пары Гб при сохранении приемлемой скорости работы.
1) Копируем данные из архива в .parquet. Проще всего прямо в CLI duckdb:
COPY
(SELECT * FROM read_csv(
"goa_uniprot_gcrp.gpa.gz",
header = false,
names = [
"DB",
"DB_Object_ID",
"Qualifier",
"GO_ID",
"DB_Reference",
"Evidence_Code",
"With_From",
"Interacting_Taxon_ID",
"Date",
"Assigned_By",
"Annotation_Extension",
"Annotation_Properties"
]
)
)
TO "goa_uniprot_gcrp.parquet"
(FORMAT "parquet");
Файл получается чуть тяжелее исходного архива, 3.44 Гб против 2.85 Гб.
2) Работаем с файлом как с таблицей на стороне R:
> library(arrow)
> library(dplyr)
> dt <- open_dataset("goa_uniprot_gcrp.parquet")
Описание таблицы можно получить за 12 с:
> tictoc::tic()
> glimpse(dt)
FileSystemDataset with 1 Parquet file
395,271,375 rows x 12 columns
$ DB <string> "UniProtKB", "UniProtKB", "Uni…
$ DB_Object_ID <string> "A0A010PZK3", "A0A010PZK3", "A…
$ Qualifier <string> "enables", "enables", "enables…
$ GO_ID <string> "GO:0004553", "GO:0016757", "G…
$ DB_Reference <string> "GO_REF:0000002", "GO_REF:0000…
$ Evidence_Code <string> "ECO:0000256", "ECO:0007826", …
$ With_From <string> "InterPro:IPR000757", "PANTHER…
$ Interacting_Taxon_ID <string> NA, NA, NA, NA, NA, NA, NA, NA…
$ Date <int64> 20241216, 20241218, 20241216, …
$ Assigned_By <string> "InterPro", "TreeGrafter", "Un…
$ Annotation_Extension <string> NA, NA, NA, NA, NA, NA, NA, NA…
$ Annotation_Properties <string> NA, NA, NA, NA, NA, NA, NA, NA…
> tictoc::toc()
12.15 sec elapsed
Подсчет количества строк для каждого evidence code занимает меньше 6 с:
> tictoc::tic()
> dt %>%
+ group_by(Evidence_Code) %>%
+ summarize(n_by_evidence = n()) %>%
+ collect()
# A tibble: 143 × 2
Evidence_Code n_by_evidence
<chr> <int>
1 ECO:0000256 140833519
2 ECO:0007826 92325252
3 ECO:0007322 124582591
4 ECO:0000501 11571884
5 ECO:0000366 6669508
6 ECO:0000307 157841
7 ECO:0000318 3648584
8 ECO:0000364 78364
9 ECO:0000315 204006
10 ECO:0000316 40467
# ℹ 133 more rows
# ℹ Use `print(n = ...)` to see more rows
> tictoc::toc()
5.73 sec elapsed
Также можно сделать arrow::to_duckdb(), или же открывать .parquet сразу средствами duckdb (как из CLI, так и при помощи пакетов на R/Python/etc). Так даже быстрее работает:> library(duckdb)
Loading required package: DBI
> con <- dbConnect(duckdb::duckdb())
> tictoc::tic()
> dt <- dbGetQuery(
+ con,
+ "SELECT count(*)
+ FROM 'goa_uniprot_gcrp.parquet'
+ GROUP BY Evidence_Code"
+ )
> tictoc::toc()
0.95 sec elapsed
Комментариев нет:
Отправить комментарий