RápidoPGS is a tool to quickly compute polygenic scores (PGS) from GWAS summary statistics datasets from either case-control (eg. asthma) or quantitative traits (eg. height and BMI).
Input GWAS summary statistics datasets should have a minimum set of columns, with these names, but in any order:
Also, if doing a PGS on a quantitative trait GWAS dataset, your file must include this:
Current RápidoPGS version (v2.1.0) is available on CRAN, so we can install it using the following code
install.packages("RapidoPGS")
Alternatively, you can download the development version from Github
(Note: If you don’t have remotes
installed, please install
it first:
if (!requireNamespace("remotes", quietly = TRUE))
install.packages("remotes")
::install_github("GRealesM/RapidoPGS") remotes
Once installed, let’s load it. This will automatically load all required dependencies.
library(RapidoPGS)
GWAS catalog is an outstanding GWAS summary statistics data source, as it not only puts together tons of public datasets, but it also uses a semi-automatic pipeline to apply quality control and liftover (a.k.a. harmonise) those datasets, thus helping overcome the problem of having GWAS sumstats in so many different formats and builds.
In this vignette, we’ll use GWAS catalog to obtain an example dataset. For this vignette we’ll use a Breast cancer (BRCA) dataset from Michailidou et al., 2017, which is one that we used in our manuscript. This GWAS was performed on 119078 controls and 137045 cases of Breast cancer.
It’s a big file, and may take a while to download, so here we will show the command to download, but actually cheat and load a subset of data already loaded.
Note that in this particular case we chose a study that contained a
single dataset. In other cases there may be more than one. In that case
gwascat.download
will prompt you with the list of available
options, prompting their accession numbers, and asking you to choose a
file by its number in the list, if running interactively. If you want to
run gwascat.download
automatically, and you know the number
already, you can supply it using filenum
argument, so R
won’t bug you.
We use it’s PubMed ID (29059683). We could download only harmonised
GWAS catalog columns (thus having a lighter file) but I don’t advise
this because sometimes we may need columns from the original file. We
then set hm_only = FALSE
to get all columns.
<- gwascat.download(29059683, hm_only = FALSE) ds
Now for the cheat: for illustrative purposes, I took a random subset from this file including 100,000 SNPs from this file, which we’ll use in this tutorial. Bear in mind that the final PGS won’t be a valid model since we randomly removed most SNPs. It will serve for our teaching purposes, though! ;)
<- michailidou ds
The first thing to do is to check what our file looks like. RápidoPGS can handle NAs in crucial columns, so don’t worry too much about that (unless you have all NA for crucial columns, of course!).
A note of caution when dealing with GWAS catalog files, though: since they use a semi-automated pipeline, it is possible that even some columns are present, they are empty, so be careful with that!
Also, RápidoPGS requires allele frequencies, so it’s possible that you need to compute it from an external reference panel (eg. 1000 Genomes Phase III). We don’t cover that step in this vignette, but we might write instructions explaining how to do it in the future.
Let’s take a look at the file!
summary(ds)
## hm_rsid hm_chrom hm_pos hm_other_allele
## Length:100000 Length:100000 Min. : 10519 Length:100000
## Class :character Class :character 1st Qu.: 31928836 Class :character
## Mode :character Mode :character Median : 69324516 Mode :character
## Mean : 78427892
## 3rd Qu.:114421523
## Max. :248906719
## hm_effect_allele hm_beta hm_effect_allele_frequency
## Length:100000 Min. :-2.9353000 Min. :0.0051
## Class :character 1st Qu.:-0.0099000 1st Qu.:0.0200
## Mode :character Median :-0.0003000 Median :0.1033
## Mean :-0.0008408 Mean :0.2230
## 3rd Qu.: 0.0095000 3rd Qu.:0.3537
## Max. : 0.6549000 Max. :0.9949
## standard_error p_value
## Min. :0.0062 Min. :0.0000
## 1st Qu.:0.0075 1st Qu.:0.1940
## Median :0.0115 Median :0.4492
## Mean :0.0197 Mean :0.4617
## 3rd Qu.:0.0259 3rd Qu.:0.7215
## Max. :1.0917 Max. :0.9993
In this case, we don’t have any missing data, which is fantastic. We’ll now prepare the dataset for RápidoPGS. We need to rename columns to something RápidoPGS can understand, and this is easy to do with data.table.
setnames(ds, old = c("hm_rsid", "hm_chrom", "hm_pos", "hm_other_allele", "hm_effect_allele", "hm_beta", "hm_effect_allele_frequency", "standard_error", "p_value"), new=c("SNPID","CHR", "BP","REF", "ALT", "BETA", "ALT_FREQ", "SE", "P"))
Now another thing to consider: RápidoPGS use only autosomes, so remove X or Y chromosomes at this step.
<- ds[CHR != "X",] ds
Now we have applied QC to our dataset, we can now compute our PGS! We can easily do that applying the next command, but bear in mind that, since we used harmonised columns, the build is hg38, so we must tell RápidoPGS about that.
In this new version, we don’t need sample size for case-control datasets. Note that if this was a quantitative trait dataset, we should inform total number of individuals (N parameter). Also, if our dataset had columns reporting the number of individuals for each SNP, we can replace N by a string specifying the column (eg. N = “sample_size”). By doing so, RápidoPGS-single will extract this information directly from the columns.
Let’s get our hands dirty! Let’s compute first a full RápidoPGS-single model. Since we used harmonised coordinates from GWAS catalog, our file is in build hg38, and we need to specify it to RápidoPGS (default is hg19).
Advanced use note: You may want to filter by and
align your dataset to an external reference. You can do that with
RápidoPGS, too, by specifying the path of your reference file at
reference
argument. This reference file should have five
columns (CHR, BP, REF, ALT, and SNPID) and be in the same
build as our summary statistics dataset. RápidoPGS currently
supports hg19 and hg38 builds.
<- rapidopgs_single(ds, trait = "cc", build = "hg38") full_PGS
## Assigning LD blocks...
## Done!
## Computing a RapidoPGS-single model for a case-control dataset...
Well, that was rápido! With increasingly big datasets, it will take a bit longer, of course.
Let’s take a look.
head(full_PGS)
## SNPID CHR BP REF ALT BETA ALT_FREQ SE P ld.block
## 1: rs117214991 9 109388299 C T 0.0929 0.0052 0.0559 0.09647 788
## 2: rs61113083 11 82946128 G A -0.0336 0.0623 0.0132 0.01086 915
## 3: rs118065272 12 71684434 G A 0.0021 0.0401 0.0219 0.92530 978
## 4: rs6067900 20 51693556 T C -0.0038 0.2610 0.0072 0.59860 1314
## 5: rs6132000 20 17808883 C T -0.0119 0.0981 0.0119 0.31710 1302
## 6: rs544195892 3 196463480 TAC T 0.0221 0.0526 0.0167 0.18470 314
## ppi weight
## 1: 9.681417e-05 8.994036e-06
## 2: 1.654291e-04 -5.558417e-06
## 3: 1.091763e-05 2.292701e-08
## 4: 3.651311e-06 -1.387498e-08
## 5: 9.688627e-06 -1.152947e-07
## 6: 1.980177e-05 4.376191e-07
We see three new columns: ld.block corresponds to the ld-detect LD block number assigned to the SNP (see manuscript for more details of where this comes from), ppi is the posterior probability that the SNP is causal, and weight is the weighted effect size (BETA * ppi) - and the column we’re interested in.
Imagine that we want a small portable PGS. We could use a threshold (eg. keep only SNPs with ppi larger than \(1e^{-4}\), a reasonable threshold) or keep the top SNPs with largest weights (in either way).
We can do that using RápidoPGS, let’s see how by using a \(1e^{-4}\) threshold.
For accuracy reasons, we recommend recomputing the PGS on just these
SNPs after the threshold was applied, so recalc = TRUE
by
default.
<- rapidopgs_single(ds, trait ="cc", build = "hg38", filt_threshold = 1e-4) PGS_1e4
## Assigning LD blocks...
## Done!
## Computing a RapidoPGS-single model for a case-control dataset...
head(PGS_1e4)
## SNPID CHR BP REF ALT BETA ALT_FREQ SE P ld.block
## 1: rs61113083 11 82946128 G A -0.0336 0.0623 0.0132 0.010860 915
## 2: rs55762932 17 33783485 C T -0.0839 0.0066 0.0457 0.066720 1198
## 3: rs17826142 16 48507898 T C 0.0503 0.0276 0.0195 0.009998 1160
## 4: rs7277048 21 17703035 C T -0.0660 0.0124 0.0330 0.045260 1324
## 5: rs141121949 4 42132514 G A -0.0491 0.0399 0.0167 0.003400 338
## 6: rs139406060 5 4690696 C T -0.0766 0.0118 0.0404 0.058160 418
## ppi weight
## 1: 0.0001656217 -5.564889e-06
## 2: 0.0001100407 -9.232416e-06
## 3: 0.0002614005 1.314845e-05
## 4: 0.0001139903 -7.523357e-06
## 5: 0.0006078236 -2.984414e-05
## 6: 0.0001113266 -8.527615e-06
You can omit recalculation by setting that argument to
FALSE
<- rapidopgs_single(ds, trait ="cc", build = "hg38", filt_threshold = 1e-4, recalc = FALSE) PGS_1e4_norecalc
## Assigning LD blocks...
## Done!
## Computing a RapidoPGS-single model for a case-control dataset...
head(PGS_1e4_norecalc)
## SNPID CHR BP REF ALT BETA ALT_FREQ SE P ld.block
## 1: rs61113083 11 82946128 G A -0.0336 0.0623 0.0132 0.010860 915
## 2: rs55762932 17 33783485 C T -0.0839 0.0066 0.0457 0.066720 1198
## 3: rs17826142 16 48507898 T C 0.0503 0.0276 0.0195 0.009998 1160
## 4: rs7277048 21 17703035 C T -0.0660 0.0124 0.0330 0.045260 1324
## 5: rs141121949 4 42132514 G A -0.0491 0.0399 0.0167 0.003400 338
## 6: rs139406060 5 4690696 C T -0.0766 0.0118 0.0404 0.058160 418
## ppi weight
## 1: 0.0001654291 -5.558417e-06
## 2: 0.0001098264 -9.214438e-06
## 3: 0.0002606787 1.311214e-05
## 4: 0.0001138967 -7.517184e-06
## 5: 0.0006072546 -2.981620e-05
## 6: 0.0001112250 -8.519836e-06
And what if we want the top 10 SNPs? Just change the
filt_threshold
argument. If it’s larger than 1, RápidoPGS
will understand that you want a top list, rather than a thresholded
result.
<- rapidopgs_single(ds, trait ="cc", build = "hg38", filt_threshold = 10) PGS_top10
## Assigning LD blocks...
## Done!
## Computing a RapidoPGS-single model for a case-control dataset...
head(PGS_top10)
## SNPID CHR BP REF ALT BETA ALT_FREQ SE P ld.block
## 1: rs79054216 11 69371625 C T 0.2309 0.0145 0.0265 3.041e-18 909
## 2: rs10788196 10 121658121 T G -0.1324 0.8495 0.0085 5.935e-55 867
## 3: rs28475635 4 174921828 G A -0.1030 0.1177 0.0098 5.256e-26 405
## 4: rs580057 3 27303612 G A 0.1038 0.5249 0.0062 9.185e-63 236
## 5: rs17756147 14 68569410 G A -0.0973 0.2310 0.0074 2.634e-39 1082
## 6: rs12997141 2 217071663 C T -0.0914 0.2349 0.0073 1.690e-35 204
## ppi weight
## 1: 1 0.2309
## 2: 1 -0.1324
## 3: 1 -0.1030
## 4: 1 0.1038
## 5: 1 -0.0973
## 6: 1 -0.0914
So those are examples of basic RápidoPGS-single usage!
Drop us a line if you encounter problems, and we’ll be happy to help.
Good luck!
Guillermo