Response to Selection based on Genomic Prediction Based on a Simulation (Pollen Pool GCA_MY)

This is the code to simulate response to selection based on genomic prediction and to generate the plot. The dataset used here is the pollen pool GCA1 data.

Load the R packages

library(parallel)
library(foreach)
library(doParallel)
library(tictoc)
library(plyr)
library(doSNOW)
library(progress)
library(reshape2)

rm(list = ls())
options(scipen = 999, digits = 5)

Reload Gamma Matrix

Gamma.mat <- readRDS("Gamma_Mat_GCA1_MY.RDS")

Entries

##### Number of Entries ##### 
row.gamma <- nrow(Gamma.mat)
n.geno <- row.gamma/2

# Take n (proportion selection)
n.1 <- round(n.geno*0.01,0)
n.5 <- round(n.geno*0.05,0)
n.10 <- round(n.geno*0.10,0)
n.15 <- round(n.geno*0.15,0)
n.20 <- round(n.geno*0.20,0)
n.30 <- round(n.geno*0.30,0)
n.50 <- round(n.geno*0.50,0)

Parallelisation setup

##### Parallelisation setup #####
n.cores <- detectCores() - 1

my.cluster <- parallel::makeCluster(n.cores, type = "PSOCK")
print(my.cluster)
## socket cluster with 7 nodes on host 'localhost'
registerDoSNOW(my.cluster)

iterations <- 100000

##### Function for separate the results in the simulation #####
comb <- function(x, ...) {
  lapply(seq_along(x),
         function(i) c(x[[i]], lapply(list(...), function(y) y[[i]])))
}

##### Progress Time ##### 
pb <- progress_bar$new(format = ":percent | Elapsed time: :elapsed eta: :eta",
                       total = iterations, clear = FALSE)

progress <- function(n){
  pb$tick()
} 

opts <- list(progress = progress)

Start Simulation

##### Start Simulation ##### 
tic()
simu.list <- foreach(i = 1:iterations, 
                     .combine = comb, .multicombine = TRUE, 
                     .options.snow = opts,
                     .init = list(list(), list(),list(),list(),list(),list(),list(),list())) %dopar% {
    
    z <- matrix(rnorm(n = row.gamma),nrow = row.gamma)
    
    w <- Gamma.mat %*% z # W matrix
    
    sim.ghat <- w[((row.gamma/2) + 1):row.gamma,] # Take the Ghat
    sim.gtrue <- w[1:(row.gamma/2),] # Take the true genotype values
    
    
    # Make a data frame for Ghat and true genotype values
    v <- data.frame(sim.ghat = sim.ghat, sim.gtrue = sim.gtrue, 
                    rank.ghat = rank(-sim.ghat), rank.gtrue = rank(-sim.gtrue), nsim = i)
    
    # Subset the data from the simu^^lation for each n
    sel.1  <- v[v$rank.ghat <= n.1, ]
    sel.5  <- v[v$rank.ghat <= n.5, ]
    sel.10 <- v[v$rank.ghat <= n.10, ]
    sel.15 <- v[v$rank.ghat <= n.15, ]
    sel.20 <- v[v$rank.ghat <= n.20, ]
    sel.30 <- v[v$rank.ghat <= n.30, ]
    sel.50 <- v[v$rank.ghat <= n.50, ]
    
    sel.1$n  <- n.1
    sel.5$n  <- n.5
    sel.10$n <- n.10
    sel.15$n <- n.15
    sel.20$n <- n.20
    sel.30$n <- n.30
    sel.50$n <- n.50
    
    # Count the best entries
    # Sel 1%
    top1.sel1  <- ifelse(length(which(sel.1$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel1  <- ifelse(length(which(sel.1$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel1  <- ifelse(length(which(sel.1$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel1 <- ifelse(length(which(sel.1$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel1 <- ifelse(length(which(sel.1$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    # Sel 5%
    top1.sel5  <- ifelse(length(which(sel.5$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel5  <- ifelse(length(which(sel.5$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel5  <- ifelse(length(which(sel.5$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel5 <- ifelse(length(which(sel.5$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel5 <- ifelse(length(which(sel.5$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    top1.sel10  <- ifelse(length(which(sel.10$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel10  <- ifelse(length(which(sel.10$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel10  <- ifelse(length(which(sel.10$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel10 <- ifelse(length(which(sel.10$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel10 <- ifelse(length(which(sel.10$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    # Sel 15%
    top1.sel15  <- ifelse(length(which(sel.15$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel15  <- ifelse(length(which(sel.15$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel15  <- ifelse(length(which(sel.15$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel15 <- ifelse(length(which(sel.15$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel15 <- ifelse(length(which(sel.15$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    # Sel 20%
    top1.sel20  <- ifelse(length(which(sel.20$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel20  <- ifelse(length(which(sel.20$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel20  <- ifelse(length(which(sel.20$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel20 <- ifelse(length(which(sel.20$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel20 <- ifelse(length(which(sel.20$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    # Sel 30%
    top1.sel30  <- ifelse(length(which(sel.30$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel30  <- ifelse(length(which(sel.30$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel30  <- ifelse(length(which(sel.30$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel30 <- ifelse(length(which(sel.30$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel30 <- ifelse(length(which(sel.30$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    # Sel 50%
    top1.sel50  <- ifelse(length(which(sel.50$rank.gtrue %in% 1 == TRUE)) == 1, 1, 0)
    top3.sel50  <- ifelse(length(which(sel.50$rank.gtrue %in% c(1:3) == TRUE)) == 3, 1, 0)
    top5.sel50  <- ifelse(length(which(sel.50$rank.gtrue %in% c(1:5) == TRUE)) == 5, 1, 0)
    top10.sel50 <- ifelse(length(which(sel.50$rank.gtrue %in% c(1:10) == TRUE)) == 10, 1, 0)
    top15.sel50 <- ifelse(length(which(sel.50$rank.gtrue %in% c(1:15) == TRUE)) == 15, 1, 0)
    
    # sel 1% results
    best.sel1  <- data.frame(nsim = i, sel = n.1, n.top1 = top1.sel1, 
                             n.top3 = top3.sel1, n.top5 = top5.sel1,
                             n.top10 = top10.sel1, n.top15 = top15.sel1)
    
    # sel 5% results
    best.sel5  <- data.frame(nsim = i, sel = n.5, n.top1 = top1.sel5, 
                             n.top3 = top3.sel5, n.top5 = top5.sel5,
                             n.top10 = top10.sel5, n.top15 = top15.sel5)
    
    # sel 10% results
    best.sel10  <- data.frame(nsim = i, sel = n.10, n.top1 = top1.sel10, 
                              n.top3 = top3.sel10, n.top5 = top5.sel10,
                              n.top10 = top10.sel10, n.top15 = top15.sel10)
    
    # sel 15% results
    best.sel15  <- data.frame(nsim = i, sel = n.15, n.top1 = top1.sel15, 
                              n.top3 = top3.sel15, n.top5 = top5.sel15,
                              n.top10 = top10.sel15, n.top15 = top15.sel15)
    
    # sel 20% results
    best.sel20  <- data.frame(nsim = i, sel = n.20, n.top1 = top1.sel20, 
                              n.top3 = top3.sel20, n.top5 = top5.sel20,
                              n.top10 = top10.sel20, n.top15 = top15.sel20)
    
    # sel 30% results
    best.sel30  <- data.frame(nsim = i, sel = n.30, n.top1 = top1.sel30, 
                              n.top3 = top3.sel30, n.top5 = top5.sel30,
                              n.top10 = top10.sel30, n.top15 = top15.sel30)
    
    # sel 50% results
    best.sel50  <- data.frame(nsim = i, sel = n.50, n.top1 = top1.sel50, 
                              n.top3 = top3.sel50, n.top5 = top5.sel50,
                              n.top10 = top10.sel50, n.top15 = top15.sel50)
    
    list(v, best.sel1, best.sel5, best.sel10,
         best.sel15, best.sel20, best.sel30, best.sel50)
  }
toc()
## 996.43 sec elapsed

Data wrangling the results

##### Extract imulated data #####
tic()
df <- simu.list[[1]]
df <- dplyr::bind_rows(df, .id = "nsim")
toc()
## 7.39 sec elapsed
#####  Correlations from the simulated data ##### 
cor(df$sim.ghat, df$sim.gtrue) # Correlation GBLUPs with the true values
## [1] 0.65244
cor(df$rank.gtrue, df$rank.ghat) # Correlation GBLUPs ranking with the true values ranking
## [1] 0.63004
##### Extract the data for each selection proprotion ##### 
sel1  <- simu.list[[2]]
sel5  <- simu.list[[3]]
sel10 <- simu.list[[4]]
sel15 <- simu.list[[5]]
sel20 <- simu.list[[6]]
sel30 <- simu.list[[7]]
sel50 <- simu.list[[8]]

sel1  <- dplyr::bind_rows(sel1 , .id = "nsim")
sel5  <- dplyr::bind_rows(sel5 , .id = "nsim")
sel10 <- dplyr::bind_rows(sel10, .id = "nsim")
sel15 <- dplyr::bind_rows(sel15, .id = "nsim")
sel20 <- dplyr::bind_rows(sel20, .id = "nsim")
sel30 <- dplyr::bind_rows(sel30, .id = "nsim")
sel50 <- dplyr::bind_rows(sel50, .id = "nsim")

##### Stack into one data frame ##### 
sel_dat <- rbind(sel1, sel5, sel10, sel15,
                 sel20, sel30, sel50)

##### Stop cluster for parallel #####
stopCluster(my.cluster)

Compute Probability

prob.best <- data.frame(dummy = 1)
tic()  
for (i in 1:5) {
  
  f <- as.formula((paste(names(sel_dat[i + 2]), "~ sel")))
  pro <- aggregate(f, sel_dat, FUN = "mean")
  
  if (i > 1) { 
    pro <- pro[-1]
  }
  prob.best <- cbind(prob.best, pro)
  
  if (i == 1) { 
    prob.best <- prob.best[-1]
  }
}
toc()  
## 3.35 sec elapsed

Data preparation for plot

## Transpose the dataset by n
final.dat <- melt(prob.best, id = "sel")
names(final.dat)[names(final.dat) == 'sel'] <- 'n'
final.dat$n <- as.numeric(final.dat$n)  

## Change the second column name
names(final.dat)[2] <- "m"

## Make a column for genotype numbers
final.dat$n.geno <- n.geno

## Make a column for the x axis of the plot (selection proportion)
final.dat$n.pct <- round(final.dat$n/final.dat$n.geno,3)*100

final.dat$m <- as.character(final.dat$m)

## Rename the rows in column m
final.dat$m <- ifelse(final.dat$m == "n.top1" , "Best 1",
                      ifelse(final.dat$m == "n.top3" , "Best 3",
                             ifelse(final.dat$m == "n.top5" , "Best 5",
                                    ifelse(final.dat$m == "n.top10" , "Best 10", "Best 15"))))

final.dat$m <- as.factor(final.dat$m)

## Arrange the level for making the plot
final.dat$m <- factor(final.dat$m,
                      levels = c("Best 1", "Best 3", "Best 5", "Best 10", "Best 15"))

# Make column for identifier of the pool and the cycles
# It is not necessary if only one plot to be made
final.dat$Pool <- "Pollen pool"
final.dat$Cycle <- "GCA1-MY"

knitr::kable(final.dat)
n m value n.geno n.pct Pool Cycle
19 Best 1 0.41851 1910 1 Pollen pool GCA1-MY
96 Best 1 0.73210 1910 5 Pollen pool GCA1-MY
191 Best 1 0.85202 1910 10 Pollen pool GCA1-MY
286 Best 1 0.90808 1910 15 Pollen pool GCA1-MY
382 Best 1 0.94084 1910 20 Pollen pool GCA1-MY
573 Best 1 0.97315 1910 30 Pollen pool GCA1-MY
955 Best 1 0.99417 1910 50 Pollen pool GCA1-MY
19 Best 3 0.07519 1910 1 Pollen pool GCA1-MY
96 Best 3 0.36895 1910 5 Pollen pool GCA1-MY
191 Best 3 0.58214 1910 10 Pollen pool GCA1-MY
286 Best 3 0.71503 1910 15 Pollen pool GCA1-MY
382 Best 3 0.80190 1910 20 Pollen pool GCA1-MY
573 Best 3 0.90168 1910 30 Pollen pool GCA1-MY
955 Best 3 0.97671 1910 50 Pollen pool GCA1-MY
19 Best 5 0.01468 1910 1 Pollen pool GCA1-MY
96 Best 5 0.18238 1910 5 Pollen pool GCA1-MY
191 Best 5 0.38785 1910 10 Pollen pool GCA1-MY
286 Best 5 0.54660 1910 15 Pollen pool GCA1-MY
382 Best 5 0.66613 1910 20 Pollen pool GCA1-MY
573 Best 5 0.82051 1910 30 Pollen pool GCA1-MY
955 Best 5 0.95322 1910 50 Pollen pool GCA1-MY
19 Best 10 0.00027 1910 1 Pollen pool GCA1-MY
96 Best 10 0.03159 1910 5 Pollen pool GCA1-MY
191 Best 10 0.13552 1910 10 Pollen pool GCA1-MY
286 Best 10 0.26880 1910 15 Pollen pool GCA1-MY
382 Best 10 0.40263 1910 20 Pollen pool GCA1-MY
573 Best 10 0.62706 1910 30 Pollen pool GCA1-MY
955 Best 10 0.88400 1910 50 Pollen pool GCA1-MY
19 Best 15 0.00001 1910 1 Pollen pool GCA1-MY
96 Best 15 0.00568 1910 5 Pollen pool GCA1-MY
191 Best 15 0.04620 1910 10 Pollen pool GCA1-MY
286 Best 15 0.12623 1910 15 Pollen pool GCA1-MY
382 Best 15 0.23454 1910 20 Pollen pool GCA1-MY
573 Best 15 0.46256 1910 30 Pollen pool GCA1-MY
955 Best 15 0.80669 1910 50 Pollen pool GCA1-MY

Make the plot

library(ggplot2)
p <- ggplot(final.dat, aes(x = n.pct, y = value)) + 
  geom_line(aes(x = n.pct, y = value, color = m, group = m)) +
  geom_point(aes(color = m, group = m)) +
  geom_label(aes(x = 0.5, y = 1.06, label = paste("N =", n.geno)),
             size    = 3.5,
             data    = final.dat,
             hjust   = 0,
             vjust   = 0.5
  ) +
  labs(caption = "Number of simulations = S = 100K") +
  scale_y_continuous(name = "Probability of selection", breaks = seq(0, 1, 0.10)) +
  scale_x_continuous(name = "Number of selected entries (n)", 
                     breaks = c(1, 5, 10, 15, 20, 30, 50),
                     labels = scales::percent_format(scale = 1, accuracy = 1)) +
  scale_colour_brewer(palette = "Set1", name = "Number of truly best entries (m)") +
  theme_bw() +
  theme(
    panel.grid.minor.x = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.background = element_blank(),
    plot.caption = element_text(size = 11),
    axis.title.y = element_text(face = "bold", size = 12),
    strip.text.x = element_text(size = 12, face = "bold"),
    strip.text.y = element_text(size = 12, face = "bold"),
    axis.title.x = element_text(face = "bold", size = 12,lineheight = 1),
    axis.text = element_text(angle = 0, hjust = 0.5, face = "bold", size = 10),
    legend.text = element_text(size = 11, face = "bold"),
    title = element_text(face = "bold", size = 11),legend.position = "bottom")

p