Skip to content

The Hardy-Weinberg principle, formulated independently by G. H. Hardy and Wilhelm Weinberg in the early 20th century, is a fundamental concept in population genetics that describes the conditions under which the genetic composition of a population remains stable from one generation to the next. It serves as a null model for understanding how genetic traits are inherited in idealised, non-evolving populations.

The Hardy-Weinberg principle is based on several key assumptions:

Large population: The population is large enough that genetic drift (random changes in allele frequencies) is negligible.

Random mating: Individuals in the population mate randomly, with no preference for particular genotypes or phenotypes.

No mutation: There is no introduction of new genetic variation by mutation.

No migration: The population is closed, with no immigration or emigration of individuals to or from other populations.

No natural selection: All genotypes are equally fit; there is no advantage or disadvantage associated with any particular genotype.

Under these assumptions, the Hardy-Weinberg principle predicts that the frequencies of alleles and genotypes in a population will remain constant from one generation to the next.

p² + 2pq + q² = (p+q)^2 = 1
freq(A_1) + freq(A_2) = p + q = 1

Simulation: Hardy Weinburg Equilibrium



### Simulation: Hardy Weinburg Equilibrium
### Author: Corey Chivers (2011)

## Random Parents > Offspring
cross <- function(parents) {
  offspring    <- c("d", "d")             # initiate a child object
  offspring[1] <- sample(parents[1, ], 1) # random parent 1
  offspring[2] <- sample(parents[2, ], 1) # random parent 2 
  return(offspring)
}

## New Population
random_mating <- function() {
  tmp_pop <- pop
  for (n in 1:N)
  {
    parents <- sample(1:N, 2)
    tmp_pop[n, ] <- cross(pop[parents, ])
  }
  pop <- tmp_pop
}

## Setting
genotypes <- c("A", "a") # Genotypes A1 / A2 or A / a
p         <- 0.5         # freq. allele A1
q         <- 1 - p       # freq. allels A2
N         <- 200         # population size
a_freq    <- c(p, q)     # allele frequencies

pop       <- array(sample(genotypes, 2 * N, p = a_freq, replace = T), dim = c(N, 2))

I               <- 200
num_generations <- 1
g_freq          <- array(dim = c(I, 3))
p_vec           <- array(dim = I)

for (i in 1:I)
{
  p <- runif(1, 0, 1)
  q <- 1 - p
  a_freq <- c(p, q)

  pop[, 1] <- sample(genotypes, N, p = a_freq, replace = T)
  pop[, 2] <- sample(genotypes, N, p = a_freq, replace = T)

  for (g in 1:num_generations) {
    random_mating()
  }

  f_aa <- 0
  f_Aa <- 0
  f_AA <- 0

  for (n in 1:N)
  {
    if (identical(pop[n, ], c("A", "A"))) {
      f_AA <- f_AA + 1
    }
    if (identical(pop[n, ], c("A", "a")) ||
      identical(pop[n, ], c("a", "A"))) {
      f_Aa <- f_Aa + 1
    }
    if (identical(pop[n, ], c("a", "a"))) {
      f_aa <- f_aa + 1
    }
  }
  f_aa <- f_aa / N
  f_Aa <- f_Aa / N
  f_AA <- f_AA / N

  g_freq[i, ] <- c(f_AA, f_Aa, f_aa)
  p_vec[i] <- p
}

## Plot

# pdf("HW.pdf")

  ## Plot the sims
  plot(p_vec,
    g_freq[, 1],
    col = "green",
    xlab = "p, or 1-q",
    ylab = ""
  )
  points(p_vec, g_freq[, 2], col = "red")
  points(p_vec, g_freq[, 3], col = "blue")

  ## Theoretical Curves
  curve(x^2, col = "green", add = T)            # f(AA)=p^2
  curve((1 - x)^2, col = "blue", add = T)       # f(aa)=(1-p)^2=q^2
  curve(2 * x * (1 - x), col = "red", add = T)  # f(Aa)=2pq=2p(p-1)

  ## GT Labels
  text(0.35, 0.95, "AA", col = "green")
  text(0.5,  0.95, "aa", col = "blue")
  text(0.65, 0.95, "Aa", col = "red")

# dev.off()

  

The Hardy-Weinberg principle provides a basis for understanding how genetic variation is maintained within populations.

Deviations from Hardy-Weinberg equilibrium indicate that one or more of the assumptions are not being met. This may indicate that factors such as mutation, migration, natural selection or non-random mating are affecting allele frequencies.

The principle is a valuable tool in population genetics for studying evolutionary processes and understanding how genetic traits are inherited and distributed within populations.


There are R packages that you can use to study Hardy-Weinberg equilibrium and perform related genetic analyses. Here are some commonly used R packages for this purpose:

The HardyWeinberg package is specifically designed for conducting tests of Hardy-Weinberg equilibrium, estimating allele frequencies, and performing other genetic analyses.

The pegas package offers a wide range of functions for population and evolutionary genetics, including Hardy-Weinberg equilibrium tests and genetic diversity calculations.

The genetics package provides functions for conducting tests of Hardy-Weinberg equilibrium, calculating various genetic statistics, and working with genetic data.