如何在R中创建含指定相关性的正态分布变量数据框?
Let's walk through this clearly—first we'll cover your initial setup, then adjust to get that 0.5 correlation between RootCause and OtherThing.
Step 1: Your Original Independent Variables
First, let's confirm your initial code for generating independent normal variables. This creates a data frame where RootCause, OtherThing, and Errors are all independent (so their correlations will be close to 0):
# Generate independent normal variables RootCause <- rnorm(500, mean = 0, sd = 9) OtherThing <- rnorm(500, mean = 0, sd = 9) Errors <- rnorm(500, mean = 0, sd = 4) # Create data frame df_independent <- data.frame(RootCause, OtherThing, Errors) # Check correlation (should be near 0) cor(df_independent$RootCause, df_independent$OtherThing)
Step 2: Generate Variables with Target Correlation (0.5)
To get RootCause and OtherThing to have a correlation of 0.5, we need to generate them as correlated normal variables instead of independent ones. Here are two reliable methods:
Method 1: Use the MASS Package (Multivariate Normal Distribution)
The mvrnorm() function from the MASS package lets you specify a covariance matrix, which we can build to get the exact correlation we want.
First, remember that covariance = correlation * sd1 * sd2. For our case:
- Both
RootCauseandOtherThinghave a standard deviation of 9, so variance = 9² = 81 - Their covariance = 0.5 * 9 * 9 = 40.5
Errorsis independent of both, so its covariances with the other two are 0, and its variance is 4² = 16
Here's the code:
# Load the MASS package (install if needed with install.packages("MASS")) library(MASS) # Define mean vector: all variables have mean 0 mean_vec <- c(0, 0, 0) # Define covariance matrix cov_mat <- matrix( c( 81, 40.5, 0, # RootCause: variance 81, cov with OtherThing 40.5, cov with Errors 0 40.5, 81, 0, # OtherThing: cov with RootCause 40.5, variance 81, cov with Errors 0 0, 0, 16 # Errors: cov with others 0, variance 16 ), nrow = 3, byrow = TRUE, dimnames = list(c("RootCause", "OtherThing", "Errors"), c("RootCause", "OtherThing", "Errors")) ) # Generate correlated variables correlated_vars <- mvrnorm(n = 500, mu = mean_vec, Sigma = cov_mat) # Convert to data frame df_correlated <- as.data.frame(correlated_vars) # Verify the correlation (should be ~0.5) cor(df_correlated$RootCause, df_correlated$OtherThing)
Method 2: Manual Linear Combination (No Extra Packages)
If you don't want to use the MASS package, you can construct OtherThing as a linear combination of RootCause and an independent normal variable. This works because:
- We keep
RootCauseas is - We create
OtherThingsuch that part of it depends onRootCause(to get the correlation) and the rest is noise (to maintain the standard deviation of 9)
The formula is:OtherThing = (correlation) * RootCause + sqrt(1 - correlation²) * independent_normal_variable
Since we want a correlation of 0.5 and a standard deviation of 9, here's how to implement it:
# Generate RootCause first RootCause <- rnorm(500, mean = 0, sd = 9) # Generate independent noise for OtherThing noise <- rnorm(500, mean = 0, sd = 9) # Construct OtherThing with 0.5 correlation to RootCause OtherThing <- 0.5 * RootCause + sqrt(1 - 0.5^2) * noise # Generate independent Errors Errors <- rnorm(500, mean = 0, sd = 4) # Create data frame df_correlated_manual <- data.frame(RootCause, OtherThing, Errors) # Verify correlation cor(df_correlated_manual$RootCause, df_correlated_manual$OtherThing)
This works because the linear combination preserves the standard deviation (since 0.5² + (sqrt(0.75))² = 0.25 + 0.75 = 1, so the total variance remains 9² = 81) and sets the exact correlation we want.
Why Your Initial Code Didn't Work
The rnorm() function generates independent random variables by default, so their correlations will always be close to 0. To get a specific non-zero correlation, you need to use methods that account for the relationship between variables (like multivariate normal or linear combinations).
内容的提问来源于stack exchange,提问作者MGaius

