Home > Net >  Generate matrices meet conditions to obtain N matrices and rbind the N accepted matrices together
Generate matrices meet conditions to obtain N matrices and rbind the N accepted matrices together

Time:10-30

I want to generate 400 compositional data which meet conditions and then combine them together. The means and variance correlations between three variables used to generate the data are:

mu <- c(45.2, 15.4, 15.4) # means
names (mu) <- c("P", "S", "Fa") # names of the three variances
sted <- c(4.830935, 3.222764, 3.222764) # standard deviations
names (sted) <- c("P", "S", "Fa") # names of the three variances

# covariance matrix: 
corMat <- matrix (c(23.337931, -7.737931, -7.737931, 
                    -7.737931, 10.386207, -5.131034,
                    -7.737931, -5.131034, 10.386207),
                  ncol = 3, byrow = T)
dimnames (corMat) <- list (row_names = c("P", "S", "Fa"),
                           col_names = c("P", "S", "Fa"))

The procedure of stimulated data generating includes two steps, as follows:

Step 1: generate a datum with a normal distribution based mean and variance correlations between three variables:

set.seed(1)
library(MASS)
dat1 <- mvrnorm(n = 1, mu = mu, Sigma = corMat, empirical = F)

Step 2: check if dat1 has: P within the range of 45 <= P <= 55; S within 12 <= S <= 22; and Fa within 12 <= S <= 22. If dat1 meets the three conditions of P, S and Fa, accept dat1. Repeat steps 1 and 2 until achieving 400 accepted data and rbind them together.

I found some questions related to repeat break such as this, but I am still stuck in repeating steps 1 and 2 till obtaining 400 data and bind the data together. Please can anyone help? Thank you very much.

CodePudding user response:

The following solves your problem. However, the generated dat1 appears to never fulfill the conditions you want to impose. Should not dat1 be divided by 100?

nSets <- 0

data <- matrix(ncol=3)

while (nSets < 400)
{
  dat1 <- mvrnorm(n = 1, mu = mu, Sigma = corMat, empirical = F)

  # dat1 <- dat1/100 <-- maybe this is necessary?

  if (dat1["P"] >= 0.45 & dat1["P"] <= 0.55 &
      dat1["S"] >= 0.12 & dat1["S"] <= 0.22 &
      dat1["Fa"] >= 0.12 & dat1["Fa"] <= 0.22)
  {
    nSets <- nSets   1
    data <- rbind(data,dat1)
  }
}

data <-  data[-1,]
  • Related