Back to Blog
PLINKFile FormatsPopulation Genetics

PLINK File Formats Explained: BED/BIM/FAM vs PGEN/PVAR/PSAM

A column-by-column guide to PLINK 1.9's .bed/.bim/.fam trio and PLINK2's native .pgen/.pvar/.psam, plus how to convert between them and VCF.

SSSudipta SardarJuly 20, 20269 min read
PLINK File Formats Explained: BED/BIM/FAM vs PGEN/PVAR/PSAM

Every GWAS, PCA, and polygenic score pipeline starts with the same unglamorous question: how do I get my genotypes into PLINK, and which cryptic three-file set am I actually looking at? Open a genotype directory and you will find files ending in .bed, .bim, and .fam, or a newer trio ending in .pgen, .pvar, and .psam. They store the same underlying idea — samples by variants by genotypes — but the layouts, the tools that read them, and the tradeoffs are different enough that mixing them up will silently waste hours. This guide walks through both trios column by column, explains why PLINK2 introduced a new one, and shows exactly how to convert between them and VCF.

A VCF stores everything — sample names, variant positions, and genotype calls — in a single text file. That is convenient for interchange but slow and bulky for the number-crunching PLINK is built for. PLINK's answer is to split the data across three files by role: one file holds the genotype matrix in a compact binary form, one describes the variants (rows), and one describes the samples (columns). Keeping metadata separate from the genotype block means PLINK can memory-map the heavy binary file and stream through millions of variants without re-parsing text on every pass.

The consequence you must remember: the three files are a set. They share a basename (mydata.bed, mydata.bim, mydata.fam) and PLINK loads them together via a single --bfile mydata flag. Delete or rename one and the others become useless, because the genotype block carries no labels of its own.

This is the classic format, produced by PLINK 1.9 and still the most widely accepted input across GWAS tools. The .bed file is a binary genotype matrix and is not human-readable — do not confuse it with the UCSC BED interval format used by tools like bedtools, which is a completely unrelated text format that happens to share the extension.

The .bed file begins with a 3-byte magic number (0x6c 0x1b 0x01) and then packs genotypes two bits each: 00 for homozygous first allele, 11 for homozygous second allele, 01 for missing, and 10 for heterozygous. Four genotypes fit in a single byte, which is why a whole-genome dataset for thousands of samples collapses to a few gigabytes. By default it is stored variant-major, meaning all samples for variant 1 come first, then all samples for variant 2.

The .fam file is a plain-text table with one row per sample and exactly six columns:

ColumnFieldMeaning
1FIDFamily ID
2IIDWithin-family (individual) ID
3PATFather's IID, or 0 if unknown
4MATMother's IID, or 0 if unknown
5SEX1 = male, 2 = female, 0/-9 = unknown
6PHENOPhenotype: 1 control, 2 case, -9/0 missing

The .bim file describes variants, one row per marker, with six columns: chromosome, variant ID (usually an rsID), genetic distance in centimorgans (often 0), base-pair position, allele 1 (conventionally the minor/ALT allele), and allele 2 (conventionally the major/REF allele).

The allele order in the .bim file is the single most common source of sign errors in downstream analysis. Allele 1 (column 5) is the counted allele — effect sizes, allele frequencies, and dosage are all reported with respect to it. It is NOT guaranteed to match the VCF REF/ALT convention, so always check with --freq before merging summary statistics or building a polygenic score.

PLINK2 introduced a new native format because the old one hit hard limits. The 2-bit encoding cannot represent dosages from imputation, phased haplotypes, multiallelic sites, or more than a handful of missing-data states. The new trio fixes all of that while staying fast.

The .pgen file is the binary genotype store, and it is far more capable: it supports variable-width records, per-variant compression, dosage data, and phase information. Crucially, it is often smaller than the equivalent .bed because PLINK2 applies context-aware compression per variant rather than a flat 2 bits.

The .pvar file replaces .bim, and here is the important upgrade — it is essentially a VCF-style variant table. It uses #CHROM POS ID REF ALT columns and can carry an INFO column plus arbitrary extra fields, so imputation quality scores or allele frequencies travel with the variants instead of being lost. Because REF and ALT are stated explicitly, the allele-order ambiguity of .bim largely disappears.

The .psam file replaces .fam. It has a header line beginning with #IID (or #FID IID) and can hold any number of named columns — multiple phenotypes, covariates, ancestry labels — rather than being frozen at six. This alone is worth the switch for anyone juggling several phenotypes.

BED/BIM/FAM vs PGEN/PVAR/PSAM at a Glance

Feature.bed/.bim/.fam.pgen/.pvar/.psam
ProducerPLINK 1.9PLINK2
Genotype encodingfixed 2-bitvariable, compressed
Dosages / imputationnot supportedsupported
Phase informationnot supportedsupported
Multiallelic variantssplit onlynative
Sample columnsfixed 6arbitrary named
Variant metadata6 columnsVCF-style, extensible
Tool compatibilityuniversalgrowing

The practical rule: use .bed/.bim/.fam when a downstream tool demands it (many older GWAS and heritability tools only read PLINK 1 binary), and use .pgen/.pvar/.psam for everything you run inside PLINK2 itself, especially imputed dosage data.

Converting Between the Formats

PLINK2 reads both trios and writes both, so it is the natural hub for conversions. To load the classic trio with --bfile and write the native one with --make-pgen:

bash
plink2 --bfile mydata \
       --make-pgen \
       --out mydata_pgen

To go the other direction — native back to classic binary, for a tool that only speaks PLINK 1 — load with --pfile and write with --make-bed:

bash
plink2 --pfile mydata_pgen \
       --make-bed \
       --out mydata_bed

Note the flag pairing: --bfile reads a .bed set, --pfile reads a .pgen set, --make-bed writes the classic trio, and --make-pgen writes the native trio. Getting these mixed up is the most common beginner stumble.

Going To and From VCF

Most public genotype data arrives as VCF, so importing is step zero of nearly every pipeline. If your VCF carries imputed dosages you want to keep, import with PLINK2 and preserve them:

bash
plink2 --vcf cohort.vcf.gz dosage=DS \
       --make-pgen \
       --out cohort

Without the dosage=DS modifier, PLINK reads only hard genotype calls and throws the dosage precision away — a quiet data-loss trap when working with imputed panels. If you understand how a VCF encodes those GT and DS fields, the import options make far more sense; see the VCF file format explained for the full field-by-field breakdown.

Exporting back to VCF is symmetric:

bash
plink2 --pfile cohort \
       --export vcf bgz \
       --out cohort_out

Before importing any VCF, normalize it. Left-align and split multiallelic records with bcftools norm -m -any -f reference.fa so that each row is a single biallelic site with a consistent representation. PLINK will otherwise split multiallelics with its own naming scheme, and the variant IDs may not line up with your reference panel. Normalizing first keeps IDs reproducible across tools.

The bcftools norm step matters because PLINK and your imputation server may resolve the same indel to different left-aligned coordinates, and mismatched positions cause variants to silently drop during a merge. If you have not set up the toolkit yet, our samtools and bcftools install guide covers getting bcftools running with conda in a few minutes.

Beyond allele order, three traps catch people repeatedly. First, strand and reference-allele flips when merging cohorts: two genotyping arrays can report the same SNP on opposite DNA strands, so a naive merge silently treats matching alleles as mismatches. Use plink2 --ref-allele to force every dataset onto the same reference allele before combining them, and drop ambiguous A/T and C/G SNPs that cannot be strand-resolved without external allele-frequency data. Second, variant ID uniqueness: if your .bim or .pvar has duplicate or missing IDs, use PLINK2's --set-all-var-ids template to build unique chr:pos:ref:alt identifiers before any merge. Third, sample ID matching across files: PLINK matches on the FID/IID pair, so a phenotype file keyed on IID alone will fail to join if your samples share IIDs across families.

Keeping genotype work reproducible is far easier when the whole conversion chain lives in a pinned environment; if you wire these plink2 and bcftools steps into a Snakemake pipeline, format conversions become a single command you can rerun on any machine.

Practical Takeaways

  • The three PLINK files are a set sharing one basename — never move or rename one without the others, because the binary genotype block carries no labels of its own.
  • In .bed/.bim/.fam, allele 1 (column 5 of the .bim) is the counted allele for frequencies and effect sizes; verify it with --freq before merging any external summary statistics.
  • Prefer .pgen/.pvar/.psam for imputed dosage data, phased genotypes, multiallelics, or multiple phenotypes; the native trio preserves information the 2-bit .bed cannot represent.
  • Convert with PLINK2 as the hub: --bfile/--pfile to read, --make-bed/--make-pgen to write, and remember dosage=DS when importing dosages from VCF.
  • Run bcftools norm -m -any -f reference.fa before importing any VCF so multiallelics are split and left-aligned with reproducible variant IDs.
  • A genomics interval .bed and a PLINK genotype .bed are entirely different files that share an extension — never assume from the suffix alone.

Get these conventions right and the rest of your population-genetics stack falls into place, because GWAS, PCA, and polygenic scoring tools all assume correctly formatted, correctly oriented genotypes. If you are still assembling the toolchain, start with a clean conda environment on bioconda channels and install plink2 and bcftools there so your cohort-processing pipeline stays reproducible from raw VCF to final analysis.