สร้างตัวแปรสุ่มที่มีความสัมพันธ์ที่กำหนดไว้กับตัวแปรที่มีอยู่


71

สำหรับการศึกษาการจำลองฉันต้องสร้างตัวแปรสุ่มที่แสดง prefined (ประชากร) ความสัมพันธ์กับตัวแปรที่มีอยู่YY

ฉันดูในRแพ็คเกจcopulaและCDVineสามารถสร้างการแจกแจงหลายตัวแปรแบบสุ่มด้วยโครงสร้างการพึ่งพาที่กำหนด อย่างไรก็ตามเป็นไปไม่ได้ที่จะแก้ไขหนึ่งในตัวแปรที่เป็นผลลัพธ์ของตัวแปรที่มีอยู่

ความคิดและลิงก์ไปยังฟังก์ชั่นที่มีอยู่นั้นได้รับการชื่นชม!


สรุป: คำตอบที่ถูกต้องสองคำขึ้นมาพร้อมกับโซลูชันที่แตกต่าง:

  1. R สคริปต์โดย Caracal ซึ่งจะคำนวณตัวแปรสุ่มกับที่แน่นอน (ตัวอย่าง) ความสัมพันธ์กับตัวแปรที่กำหนดไว้ล่วงหน้า
  2. R ฟังก์ชั่นฉันพบตัวเองซึ่งจะคำนวณตัวแปรสุ่มที่มีการกำหนดประชากรความสัมพันธ์กับตัวแปรที่กำหนดไว้ล่วงหน้า

[@ttnphns 'นอกจากนี้: ฉันใช้เสรีภาพในการขยายชื่อคำถามจากกรณีตัวแปรคงที่เดียวเป็นจำนวนคงที่ของตัวแปรคงที่; เช่นวิธีการสร้างตัวแปรที่มีคอร์เรชั่นที่กำหนดไว้ล่วงหน้าพร้อมกับตัวแปรคงที่บางตัวที่มีอยู่]


2
ดูคำถามนี้ที่เกี่ยวข้องstats.stackexchange.com/questions/13382/ซึ่งคำถามของคุณโดยตรง (อย่างน้อยด้านทฤษฎีของมัน)
มาโคร

ต่อไปนี้ Q นอกจากนี้ยังมีความสัมพันธ์อย่างยิ่งและจะเป็นที่สนใจ: วิธีการสร้างตัวเลขสุ่มมีลักษณะร่วมกัน (ได้รับหมายถึงความแปรปรวนและระดับของความสัมพันธ์)
gung

คำตอบ:


56

นี่คืออีกอันหนึ่ง: สำหรับเวกเตอร์ที่มีค่าเฉลี่ย 0 ความสัมพันธ์ของพวกเขาเท่ากับโคไซน์ของมุม ดังนั้นวิธีหนึ่งที่จะหาเวกเตอร์ที่มีค่าสหสัมพันธ์ที่ต้องการ, ตรงกับมุม :r θxrθ

  1. รับเวกเตอร์คงที่และเวกเตอร์สุ่มx1x2
  2. ศูนย์ทั้งเวกเตอร์ (หมายถึง 0), ให้เวกเตอร์ , ˙ x 2x˙1x˙2
  3. ทำให้ orthogonal เป็น (ฉายไปยังพื้นที่ย่อย orthogonal) โดยให้ ˙ x 1 ˙ x 2x˙2x˙1x˙2
  4. ขนาดและถึงความยาว 1 โดยให้ และ ˙ x 2 ˉ x 1 ˉ x 2x˙1x˙2x¯1x¯2
  5. ˉ x 1θ ˉ x 1Rx1x¯2+(1/tan(θ))x¯1เป็นเวกเตอร์ที่มีมุมเป็น เป็นและมีความสัมพันธ์กับ จึงเป็นRนี่ก็เป็นความสัมพันธ์กับเนื่องจากการแปลงเชิงเส้นทำให้ความสัมพันธ์ไม่เปลี่ยนแปลงx¯1θx¯1rx1

นี่คือรหัส:

n     <- 20                    # length of vector
rho   <- 0.6                   # desired correlation = cos(angle)
theta <- acos(rho)             # corresponding angle
x1    <- rnorm(n, 1, 1)        # fixed given data
x2    <- rnorm(n, 2, 0.5)      # new random data
X     <- cbind(x1, x2)         # matrix
Xctr  <- scale(X, center=TRUE, scale=FALSE)   # centered columns (mean 0)

Id   <- diag(n)                               # identity matrix
Q    <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))      # QR-decomposition, just matrix Q
P    <- tcrossprod(Q)          # = Q Q'       # projection onto space defined by x1
x2o  <- (Id-P) %*% Xctr[ , 2]                 # x2ctr made orthogonal to x1ctr
Xc2  <- cbind(Xctr[ , 1], x2o)                # bind to matrix
Y    <- Xc2 %*% diag(1/sqrt(colSums(Xc2^2)))  # scale columns to length 1

x <- Y[ , 2] + (1 / tan(theta)) * Y[ , 1]     # final new vector
cor(x1, x)                                    # check correlation = rho

ป้อนคำอธิบายรูปภาพที่นี่

สำหรับฉากฉายผมใช้ -decomposition เพื่อปรับปรุงเสถียรภาพตัวเลขตั้งแต่นั้นมาก็Q'Q R P = Q Q PQRP=QQ


ฉันพยายามเขียนรหัสลงในไวยากรณ์ SPSS อีกครั้ง ฉันสะดุดการสลายตัว QR ของคุณซึ่งส่งกลับคอลัมน์ 20x1 ใน SPSS ฉันมี Gram-Schmidt orthonormalization (ซึ่งก็คือการสลายตัว QR) แต่ไม่สามารถทำซ้ำคอลัมน์ Q ผลลัพธ์ของคุณ คุณสามารถเคี้ยวมากกว่าการกระทำ QR ของคุณกับฉันได้ไหม หรือระบุวิธีการทำงานบางอย่างเพื่อให้ได้เส้นโครง ขอบคุณ
ttnphns

@caracal P <- X %*% solve(t(X) %*% X) %*% t(X)ไม่ได้ผลิต r = 0.6 ดังนั้นจึงไม่ใช่วิธีแก้ปัญหา ฉันยังสับสนอยู่ (ฉันมีความสุขที่จะเลียนแบบการแสดงออกของคุณQ <- qr.Q(qr(Xctr[ , 1, drop=FALSE]))ในโปรแกรม SPSS แต่ไม่ทราบว่า.)
ttnphns

@ttnphns ขออภัยในความสับสนความคิดเห็นของฉันมีไว้สำหรับกรณีทั่วไป นำไปใช้กับสถานการณ์ในตัวอย่าง: การรับเมทริกซ์การฉายภาพผ่าน QR-decomposition เป็นเพียงความมั่นคงเชิงตัวเลข คุณจะได้รับการฉายเมทริกซ์เป็นถ้าสเปซจะทอดคอลัมน์ของเมทริกซ์Xใน R คุณสามารถเขียนนี่เพราะสเปซจะทอดคอลัมน์แรกของ เมทริกซ์สำหรับการฉายลงบนส่วนประกอบมุมฉากคือ IP XP=X(XX)1XXXctr[ , 1] %*% solve(t(Xctr[ , 1]) %*% Xctr[ , 1]) %*% t(Xctr[ , 1])Xctr
caracal

4
ใครสามารถอธิบายวิธีการทำสิ่งที่คล้ายกันสำหรับมากกว่าสองตัวอย่าง? บอกว่าถ้าฉันต้องการตัวอย่าง 3 ตัวอย่างที่มีความสัมพันธ์แบบคู่กับ rho ฉันจะเปลี่ยนวิธีแก้ปัญหานี้เพื่อให้บรรลุได้อย่างไร
Andre Terra

สำหรับกรณีขีด จำกัดrho=1ฉันพบว่ามีประโยชน์ที่จะทำสิ่งนี้: if (isTRUE(all.equal(rho, 1))) rho <- 1-10*.Machine$double.epsมิฉะนั้นฉันได้รับNaNs
PatrickT

19

ฉันจะอธิบายวิธีแก้ปัญหาที่เป็นไปได้ทั่วไปที่สุด การแก้ปัญหาในรุ่นนี้ช่วยให้เราสามารถใช้งานซอฟต์แวร์ที่มีขนาดกะทัดรัดได้อย่างน่าทึ่งเพียงแค่Rโค้ดสั้น ๆ สองบรรทัด

เลือกเวกเตอร์ของยาวเช่นเดียวกับ , ตามการกระจายใด ๆ ที่คุณชอบ Letจะเหลือของสี่เหลี่ยมถดถอยน้อยของกับ : นี้สารสกัดจากส่วนประกอบจากXโดยการเพิ่มกลับมาหลายที่เหมาะสมของจะเราอาจผลิตเวกเตอร์ที่มีความสัมพันธ์ใด ๆ ที่ต้องการกับYจนถึงค่าคงที่สารเติมแต่งโดยพลการและค่าคงที่การคูณเชิงบวก - ซึ่งคุณมีอิสระที่จะเลือกในทางใด ๆ - การแก้ปัญหาคือY Y X Y Y X Y Y ρ YXYYXYYXYYρY

XY;ρ=ρSD(Y)Y+1ρ2SD(Y)Y.

(" " ย่อมาจากการคำนวณตามสัดส่วนกับส่วนเบี่ยงเบนมาตรฐาน)SD


นี่คือRรหัสการทำงาน หากคุณไม่ระบุโค้ดจะดึงค่าจากการแจกแจงปกติแบบหลายตัวแปรมาตรฐานX

complement <- function(y, rho, x) {
  if (missing(x)) x <- rnorm(length(y)) # Optional: supply a default if `x` is not given
  y.perp <- residuals(lm(x ~ y))
  rho * sd(y.perp) * y + y.perp * sd(y) * sqrt(1 - rho^2)
}

เพื่อแสดงให้เห็นว่าฉันสร้างสุ่มโดยมีส่วนประกอบและสร้างซึ่งมีความสัมพันธ์ต่าง ๆ ที่ระบุกับนี้ พวกเขาถูกสร้างขึ้นทั้งหมดที่มีเวกเตอร์เริ่มต้นเดียวกัน50) นี่คือแผนการกระจายของพวกเขา "rugplots" ที่ด้านล่างของแต่ละแผงแสดงเวกเตอร์ทั่วไป50 X Y ; ρ Y X = ( 1 , 2 , ... , 50 ) YY50XY;ρYX=(1,2,,50)Y

รูป

มีความคล้ายคลึงกันที่น่าทึ่งในแปลงไม่มี :-)


หากคุณต้องการทดสอบนี่คือรหัสที่สร้างข้อมูลและตัวเลขเหล่านี้ (ฉันไม่ได้รำคาญที่จะใช้อิสระในการเลื่อนและปรับขนาดผลลัพธ์ซึ่งใช้งานง่าย)

y <- rnorm(50, sd=10)
x <- 1:50 # Optional
rho <- seq(0, 1, length.out=6) * rep(c(-1,1), 3)
X <- data.frame(z=as.vector(sapply(rho, function(rho) complement(y, rho, x))),
                rho=ordered(rep(signif(rho, 2), each=length(y))),
                y=rep(y, length(rho)))

library(ggplot2)
ggplot(X, aes(y,z, group=rho)) + 
  geom_smooth(method="lm", color="Black") + 
  geom_rug(sides="b") + 
  geom_point(aes(fill=rho), alpha=1/2, shape=21) +
  facet_wrap(~ rho, scales="free")

BTW วิธีนี้ได้อย่างง่ายดาย generalizes มากกว่าหนึ่ง : ถ้าเป็นไปได้ในทางคณิตศาสตร์ก็จะได้พบกับมีความสัมพันธ์ที่ระบุไว้กับทั้ง ชุดY_iเพียงใช้สี่เหลี่ยมจัตุรัสขั้นต่ำธรรมดาเพื่อแยกเอฟเฟกต์ของทั้งหมดจากและสร้างการผสมผสานเชิงเส้นที่เหมาะสมของและส่วนที่เหลือ (มันช่วยในการทำสิ่งนี้ในแง่ของพื้นฐานสองประการสำหรับซึ่งได้มาจากการคำนวณหลอกแบบผกผันรหัส follownig ใช้ SVD ของเพื่อทำสิ่งนั้นให้สำเร็จ)X Y 1 , Y 2 , , Y k ; ρ 1 , ρ 2 , ... , ρ k Y ฉันY ฉัน X Y ฉัน Y YYXY1,Y2,,Yk;ρ1,ρ2,,ρkYiYiXYiYY

นี่คือภาพร่างของอัลกอริทึมRที่ถูกกำหนดให้เป็นคอลัมน์ของเมทริกซ์:Yiy

y <- scale(y)             # Makes computations simpler
e <- residuals(lm(x ~ y)) # Take out the columns of matrix `y`
y.dual <- with(svd(y), (n-1)*u %*% diag(ifelse(d > 0, 1/d, 0)) %*% t(v))
sigma2 <- c((1 - rho %*% cov(y.dual) %*% rho) / var(e))
return(y.dual %*% rho + sqrt(sigma2)*e)

ต่อไปนี้เป็นการใช้งานที่สมบูรณ์ยิ่งขึ้นสำหรับผู้ที่ต้องการทดสอบ

complement <- function(y, rho, x) {
  #
  # Process the arguments.
  #
  if(!is.matrix(y)) y <- matrix(y, ncol=1)
  if (missing(x)) x <- rnorm(n)
  d <- ncol(y)
  n <- nrow(y)
  y <- scale(y) # Makes computations simpler
  #
  # Remove the effects of `y` on `x`.
  #
  e <- residuals(lm(x ~ y))
  #
  # Calculate the coefficient `sigma` of `e` so that the correlation of
  # `y` with the linear combination y.dual %*% rho + sigma*e is the desired
  # vector.
  #
  y.dual <- with(svd(y), (n-1)*u %*% diag(ifelse(d > 0, 1/d, 0)) %*% t(v))
  sigma2 <- c((1 - rho %*% cov(y.dual) %*% rho) / var(e))
  #
  # Return this linear combination.
  #
  if (sigma2 >= 0) {
    sigma <- sqrt(sigma2) 
    z <- y.dual %*% rho + sigma*e
  } else {
    warning("Correlations are impossible.")
    z <- rep(0, n)
  }
  return(z)
}
#
# Set up the problem.
#
d <- 3           # Number of given variables
n <- 50          # Dimension of all vectors
x <- 1:n         # Optionally: specify `x` or draw from any distribution
y <- matrix(rnorm(d*n), ncol=d) # Create `d` original variables in any way
rho <- c(0.5, -0.5, 0)          # Specify the correlations
#
# Verify the results.
#
z <- complement(y, rho, x)
cbind('Actual correlations' = cor(cbind(z, y))[1,-1],
      'Target correlations' = rho)
#
# Display them.
#
colnames(y) <- paste0("y.", 1:d)
colnames(z) <- "z"
pairs(cbind(z, y))

นี่เป็นทางออกที่ดี อย่างไรก็ตามฉันไม่สามารถขยายตัวเองเป็นตัวแปรหลายตัว (ตัวแปรคงที่ในคำตอบของคุณ) กรณี คุณเรียกร้อง คุณสามารถแสดงมันได้หรือไม่ กรุณาด้วยรหัสกำกับประกอบที่อ่านได้โดยผู้ใช้ที่ไม่ใช่ R? YBTW, this method readily generalizes to more... Just use ordinary least squares... and form a suitable linear combination
ttnphns

1
@ttnphns ฉันได้ทำเช่นนั้น
whuber

1
ขอบคุณมาก! ฉันเห็นและฉันได้เขียนแนวทางของคุณวันนี้ใน SPSS สำหรับตัวเอง ข้อเสนอที่ยอดเยี่ยมของคุณจริงๆ ฉันไม่เคยนึกถึงความคิดพื้นฐานสองเท่าที่เกี่ยวข้องกับการแก้ปัญหา
ttnphns

เป็นไปได้ไหมที่จะใช้วิธีการคล้ายกันเพื่อหาเวกเตอร์ที่กระจายอย่างสม่ำเสมอ? นั่นคือฉันมีเวกเตอร์ที่มีอยู่xและต้องการสร้างเวกเตอร์ใหม่ที่yสัมพันธ์กับxแต่ยังต้องการให้yเวกเตอร์มีการกระจายอย่างสม่ำเสมอ
Skumin

@Skumin พิจารณาใช้ copula เพื่อให้คุณสามารถควบคุมความสัมพันธ์ระหว่างสองเวกเตอร์
whuber

6

ต่อไปนี้เป็นวิธีการคำนวณอีกวิธีหนึ่ง (โซลูชันนี้ดัดแปลงจากโพสต์ฟอรัมโดย Enrico Schumann) ตาม Wolfgang (ดูความคิดเห็น) นี้เป็นเหมือนการคำนวณที่นำเสนอโดย ttnphns

ในทางตรงกันข้ามกับวิธีการแก้ปัญหา Caracal มันไม่ได้ผลิตตัวอย่างที่มีความสัมพันธ์ที่แน่นอนของแต่สองเวกเตอร์ที่มีความสัมพันธ์ประชากรเท่ากับ\ρρρ

ฟังก์ชั่นดังต่อไปนี้สามารถคำนวณการแจกแจงตัวอย่าง bivariate ที่ดึงมาจากประชากรด้วยกำหนด มันคำนวณสองตัวแปรสุ่มหรือใช้หนึ่งตัวแปรที่มีอยู่ (ผ่านเป็นพารามิเตอร์) และสร้างตัวแปรที่สองที่มีความสัมพันธ์ที่ต้องการ:ρx

# returns a data frame of two variables which correlate with a population correlation of rho
# If desired, one of both variables can be fixed to an existing variable by specifying x
getBiCop <- function(n, rho, mar.fun=rnorm, x = NULL, ...) {
     if (!is.null(x)) {X1 <- x} else {X1 <- mar.fun(n, ...)}
     if (!is.null(x) & length(x) != n) warning("Variable x does not have the same length as n!")

     C <- matrix(rho, nrow = 2, ncol = 2)
     diag(C) <- 1

     C <- chol(C)

     X2 <- mar.fun(n)
     X <- cbind(X1,X2)

     # induce correlation (does not change X1)
     df <- X %*% C

     ## if desired: check results
     #all.equal(X1,X[,1])
     #cor(X)

     return(df)
}

mar.funฟังก์ชั่นยังสามารถใช้การแจกแจงร่อแร่ไม่ปกติโดยการปรับพารามิเตอร์ แต่โปรดทราบว่าการแก้ไขตัวแปรหนึ่งเดียวที่ดูเหมือนว่าจะทำงานร่วมกับตัวแปรกระจายตามปกติx! (ซึ่งอาจเกี่ยวข้องกับความคิดเห็นของมาโคร)

โปรดทราบว่า "ปัจจัยการแก้ไขเล็ก ๆ " จากโพสต์ต้นฉบับถูกลบออกเนื่องจากดูเหมือนว่าจะมีอคติกับความสัมพันธ์ที่เกิดขึ้นอย่างน้อยในกรณีของการแจกแจงแบบเกาส์และเพียร์สันสหสัมพันธ์ (ดูความคิดเห็น)


ดูเหมือนว่านี้เป็นเพียงการแก้ปัญหาโดยประมาณคือความสัมพันธ์เชิงประจักษ์ไม่ว่าเท่ากับ\หรือฉันกำลังพลาดอะไรอยู่? ρ
caracal

1
มันง่ายที่จะแสดงให้เห็นว่ายกเว้น "การแก้ไขเล็ก ๆ ถึง rho" (ซึ่งมีจุดประสงค์ในบริบทนี้ทำให้ฉันหลง) สิ่งนี้ก็เหมือนกับสิ่งที่แนะนำไว้ก่อนหน้านี้ วิธีการนั้นขึ้นอยู่กับการสลายตัวของ Choleski ของเมทริกซ์สหสัมพันธ์เพื่อให้ได้เมทริกซ์การแปลงที่ต้องการ ดูตัวอย่างเช่น: en.wikipedia.org/wiki/... และใช่นี้เท่านั้นที่จะทำให้คุณสองเวกเตอร์ที่มีประชากรrhoสัมพันธ์เท่ากับ
Wolfgang

"การแก้ไขขนาดเล็กเพื่อ Rho" อยู่ในโพสต์ต้นฉบับและมีการอธิบายที่นี่ จริงๆแล้วฉันไม่เข้าใจจริงๆ แต่การสืบสวนของความสัมพันธ์ 50000 จำลองกับโร = 0.3 แสดงให้เห็นว่าโดยไม่ต้อง "การแก้ไขเล็ก" ค่าเฉลี่ยของ R ของ 0.299 ผลิตในขณะที่มีการแก้ไขค่าเฉลี่ยของ .312 (ซึ่งเป็นค่าของโรแก้ไข) เป็น ผลิต ดังนั้นฉันจึงลบส่วนนั้นออกจากฟังก์ชั่น
เฟลิกซ์ S

ฉันรู้ว่ามันเก่า แต่ฉันก็อยากจะทราบด้วยว่าวิธีนี้จะไม่ได้ผลกับเมทริกซ์สหสัมพันธ์แบบไม่แน่นอน เช่น - ความสัมพันธ์ของ -1
zzk

1
ขอบคุณ; ฉันสังเกตเห็นว่าหาก x1 ไม่ได้เป็นค่าเฉลี่ยมาตรฐาน = 0, sd = 1 และคุณไม่ต้องการขายใหม่คุณจะต้องแก้ไขบรรทัด: X2 <- mar.fun(n)เพื่อX2 <- mar.fun(n,mean(x),sd(x))ให้ได้ค่าสหสัมพันธ์ที่ต้องการระหว่าง x1 และ x2
Dave M

6

ให้เป็นตัวแปรคงที่ของคุณและคุณต้องการสร้างตัวแปรที่มีความสัมพันธ์กับตามจำนวนRถ้าเป็นมาตรฐานแล้ว (เพราะคือค่าสัมประสิทธิ์เบต้าในการถดถอยง่าย)ที่เป็นตัวแปรสุ่มจากการแจกแจงแบบปกติที่มีค่าเฉลี่ยและ2} ความสัมพันธ์ระหว่างการสังเกตและข้อมูลจะอยู่ที่ประมาณ ; และสามารถมองเห็นเป็นตัวอย่างแบบสุ่มจากประชากรปกติ bivariate (ถ้าY X R X R Y = R X + E E 0 sd = XYXrXrY=rX+EE0 XYrXYXρ=rsd=1r2XYrXYXจากปกติ) กับ rρ=r

ตอนนี้ถ้าคุณต้องการที่จะบรรลุความสัมพันธ์ในตัวอย่าง bivariate ของคุณตรง , คุณจำเป็นต้องให้ที่มีศูนย์ความสัมพันธ์กับXสามารถเข้าถึงได้โดยการแก้ไขซ้ำ ๆ ด้วยตัวแปรเพียงสองตัวหนึ่งตัวที่ได้รับ ( ) และอีกตัวที่จะสร้าง ( ) จำนวนการทำซ้ำที่เพียงพอคือจริง ๆ แล้ว 1 แต่ด้วยตัวแปรที่กำหนดหลายตัว ( ) จะต้องมีการทำซ้ำE X E X Y X 1 , X 2 , X 3 , . .rEXEXYX1,X2,X3,...

ควรสังเกตว่าถ้าเป็นปกติจากนั้นในขั้นตอนแรก ("ประมาณ ")ก็จะเป็นปกติเช่นกัน อย่างไรก็ตามในการทำซ้ำอย่างเหมาะสมของกับ "แน่นอน"มีแนวโน้มที่จะสูญเสียความปกติเพราะการหาช่องโหว่ที่เหมาะสมค่ากรณีเลือกR Y Y r YXrYYrY


อัปเดต 11 พ.ย. 2560 ฉันเจอกระทู้เก่าวันนี้และตัดสินใจที่จะขยายคำตอบของฉันด้วยการแสดงอัลกอริทึมของการทำซ้ำที่เหมาะสมซึ่งฉันกำลังพูดในตอนแรก

นี่คือวิธีการแก้ปัญหาซ้ำวิธีการฝึกอบรมแบบสุ่มจำลองหรือ preexistent ตัวแปร จะมีความสัมพันธ์หรือตัวแปรร่วมได้อย่างแม่นยำในขณะที่เราต้องการ (หรืออย่างใกล้ชิดเพื่อให้ - จำนวนของการทำซ้ำขึ้นอยู่) กับชุดของตัวแปรที่กำหนด s (เหล่านี้ไม่สามารถแก้ไข)Y X

Disclamer: วิธีแก้ปัญหาแบบวนซ้ำนี้ฉันพบว่าด้อยกว่าตัวที่ยอดเยี่ยมโดยอาศัยการหาพื้นฐานสองด้านและเสนอโดย @whuber ในหัวข้อนี้ในวันนี้ @ วิธีแก้ปัญหาของ whuber ไม่ได้ทำซ้ำและที่สำคัญยิ่งกว่าสำหรับฉันดูเหมือนว่าจะส่งผลกระทบต่อค่าของตัวแปร "หมู" ที่ป้อนเข้าน้อยกว่าอัลกอริทึม "ฉัน" (มันจะเป็นสินทรัพย์ถ้างานนั้น "ถูกต้อง" ตัวแปรที่มีอยู่และไม่สร้างตัวแปรสุ่มตั้งแต่เริ่มต้น) แต่ถึงกระนั้นฉันกำลังเผยแพร่ของฉันสำหรับความอยากรู้และเพราะมันใช้งานได้ (ดูเชิงอรรถ)

ดังนั้นเราจึงได้กำหนดตัวแปร (คงที่)และ varibleซึ่งเป็นเพียงค่า "หมู" ที่สร้างขึ้นแบบสุ่มหรือเป็นตัวแปรข้อมูลที่มีอยู่ซึ่งค่าที่เราต้อง "ถูกต้อง" - เพื่อนำมาตรงกับสหสัมพันธ์ (หรืออาจเป็นโค )กับ s ข้อมูลทั้งหมดจะต้องต่อเนื่อง กล่าวอีกนัยหนึ่งควรมีคุณค่าที่เป็นเอกลักษณ์X1,X2,...,XmYYr1,r2,...,rmX

แนวคิด: ทำการวนซ้ำที่เหมาะสมของสารตกค้าง เมื่อทราบความสัมพันธ์ (เป้าหมาย) ที่ต้องการ / ความแปรปรวนร่วมเราอาจคำนวณค่าที่ทำนายไว้สำหรับโดยใช้ s เป็นตัวทำนายเชิงเส้นหลายเส้น หลังจากได้รับค่าตกค้างเริ่มต้น (จากปัจจุบันและการทำนายอุดมคติ) ฝึกพวกมันซ้ำ ๆ เพื่อไม่ให้สัมพันธ์กับตัวทำนาย ในท้ายที่สุดฟื้นกับสิ่งตกค้าง (ขั้นตอนคือการคิดค้นการทดลองล้อของฉันเองเมื่อหลายปีก่อนเมื่อฉันไม่รู้ทฤษฎีเลยฉันเขียนมันใน SPSS)YXYY

  1. แปลงเป้าหมายเพื่อผลรวมของ crossproducts โดยคูณพวกเขาโดย :{} (เป็นดัชนีตัวแปร )rdf=n1Sj=rjdfjX

  2. Z ทำให้ตัวแปรทั้งหมดเป็นมาตรฐาน (จัดกึ่งกลางแต่ละตัวจากนั้นหารด้วย st. ส่วนเบี่ยงเบนที่คำนวณจากข้างบน ) และ s จึงเป็นมาตรฐาน จำนวนเงินที่สังเกตของสี่เหลี่ยมอยู่ในขณะนี้ ={}dfYXdf

  3. คำนวณค่าสัมประสิทธิ์ regressional ทำนายโดย s ตามเป้าหมาย s:SYXrb=(XX)1S

  4. Compute คาดการณ์ค่า :XbYY^=Xb

  5. คำนวณเหลือ{Y}E=YY^

  6. คำนวณความจำเป็น (เป้าหมาย) ผลรวมของสี่เหลี่ยมสำหรับเหลือ:{Y}}SSS=dfSSY^

  7. (เริ่มต้นทำซ้ำ) คำนวณผลรวมที่สังเกตได้ของ crossproducts ระหว่างปัจจุบันและทุกๆ :EXjCj=i=1nEiXij

  8. ค่าที่ถูกต้องของโดยมีจุดประสงค์เพื่อให้ทั้งหมดใกล้ถึง (เป็นดัชนีกรณี):EC0i

    Ei[corrected]=Eij=1mCjXijnj=1mXij2

    (ตัวส่วนจะไม่เปลี่ยนแปลงในการคำนวณซ้ำคำนวณล่วงหน้า)

    หรือหรือสูตรที่มีประสิทธิภาพมากขึ้นนอกจากนี้ยังมั่นใจได้ค่าเฉลี่ยของจะกลายเป็น0ขั้นแรกให้ทำศูนย์ในแต่ละการคำนวณซ้ำก่อนการคำนวณ s ในขั้นตอนที่ 7 จากนั้นในขั้นตอนที่ 8 นี้ให้แก้ไขดังนี้:E0 EC

    Ei[corrected]=Eij=1mCjXij3i=1nXij2j=1mXij2

    (อีกครั้งเป็นที่รู้จักล่วงหน้าส่วน)1

  9. นำไปยังค่าเป้าหมาย:SSEEi[corrected]=EiSSS/SSE

    ไปที่ขั้นตอนที่ 7 (ทำพูดการทำซ้ำ 10-20 ครั้งยิ่งต้องมีการทำซ้ำมากกว่าหากเป้าหมาย s เป็นจริงจะเป็นบวกและถ้าขนาดตัวอย่างไม่น้อยเกินไปการทำซ้ำเสมอ ตรงไปบรรจบกันสิ้นสุดการวนซ้ำ)mrSSSn

  10. พร้อม: ทั้งหมด s เกือบจะเป็นศูนย์ในขณะนี้ซึ่งหมายความว่าเหลือได้รับการฝึกอบรมในการเรียกคืนเป้าหมาย s คำนวณเหมาะสม : EE R Y Y [ แก้ไข] = Y + ECErYY[corrected]=Y^+E

  11. ได้รับเกือบเป็นมาตรฐาน ในฐานะจังหวะสุดท้ายคุณอาจต้องการสร้างมาตรฐานให้แม่นยำเหมือนที่คุณทำในขั้นตอนที่ 2Y

  12. คุณสามารถให้กับความแปรปรวนและหมายความว่าคุณชอบ ที่จริงแล้วในบรรดาสี่สถิติ - min , max , mean , st. นักพัฒนา - คุณสามารถเลือกสองค่าและแปลงตัวแปรเชิงเส้นดังนั้นมันจึงโพสท่าโดยไม่ต้องเปลี่ยน s (สหสัมพันธ์) ที่คุณได้รับ (ทั้งหมดเรียกว่าการลดขนาดเชิงเส้น)RYr

เพื่อเตือนอีกครั้งถึงสิ่งที่ได้กล่าวไว้ข้างต้น เมื่อดึงไปที่ผลลัพธ์จึงไม่จำเป็นต้องกระจายตามปกติr YYrY


Y X1สูตรการแก้ไขอาจจะมีความซับซ้อนต่อไปตัวอย่างเช่นการทำประกันมากขึ้นhomoscedasticity (ในแง่ของผลรวมของสี่เหลี่ยม) ของทุกเป็นอย่างดีพร้อมกันกับการบรรลุความสัมพันธ์ที่ - ฉันได้ใช้รหัสว่า เกินไป. (ฉันไม่ทราบว่างาน "double" ดังกล่าวสามารถแก้ไขได้ผ่านวิธีการที่เป็นระเบียบมากขึ้นและไม่มีความหมายเช่นwhuber's )YX


1
ขอบคุณสำหรับคำตอบ. นั่นเป็นวิธีแก้ปัญหาเชิงประจักษ์ / ซ้ำที่ฉันคิดเช่นกัน อย่างไรก็ตามสำหรับการจำลองสถานการณ์ของฉันฉันต้องการโซลูชันการวิเคราะห์ที่มากขึ้น โชคดีที่ฉันเพิ่งพบวิธีแก้ปัญหาที่ฉันจะโพสต์ในไม่ช้า ...
เฟลิกซ์ S

สิ่งนี้ใช้ได้กับการสร้างบรรทัดฐานแบบ bivariate แต่ไม่ได้ผลสำหรับการแจกแจงโดยพลการ (หรือการแจกแจงที่ไม่ใช่ 'การย่อ')
มาโคร

1
ฉันไม่เห็นสาเหตุที่คุณเสนอซ้ำเมื่อคุณสามารถสร้างกรวยของการแก้ปัญหาทั้งหมดโดยตรง มีจุดประสงค์พิเศษสำหรับแนวทางนี้หรือไม่?
whuber

1
การแก้ไขครั้งล่าสุดของคุณ: เนื่องจากฉันได้จัดทำสูตรอย่างง่ายสำหรับโซลูชันทั้งหมดเราจึงสามารถบรรลุวัตถุประสงค์ที่ต้องการเช่น "ยิ่งใหญ่ homoscedasticity" โดยลดฟังก์ชันวัตถุประสงค์ที่เหมาะสมให้น้อยที่สุดกับชุดของโซลูชันทั้งหมด วิธีการทั่วไปอย่างเต็มที่ โดยการขยายตัวแปร (หรือตัวแปร)ไปเป็นพื้นฐานฉากและใช้ประโยชน์จากสเกลค่าคงที่ของความสัมพันธ์ปัญหาจะกลายเป็นหนึ่งในการเพิ่มประสิทธิภาพของฟังก์ชั่นที่กำหนดไว้บนทรงกลมในอวกาศยูคลิด Y
whuber

1
@ ความคิดเห็นของคุณคือสิ่งที่ฉันรออยู่ จริง ๆ แล้วคำตอบของฉัน (เกี่ยวกับความแตกต่างที่มีความสำคัญซึ่งฉันเชื่อมโยง) มีวัตถุประสงค์เพื่อเป็นความท้าทายสำหรับคุณ: บางทีมันอาจเป็นการเชื้อเชิญให้โพสต์โซลูชั่นของคุณ - อย่างละเอียดและยอดเยี่ยมเหมือนที่คุณทำ
ttnphns

4

ฉันรู้สึกเหมือนกำลังเขียนโปรแกรมบางอย่างดังนั้นฉันจึงตอบ @ ลบของ Adam และตัดสินใจที่จะเขียนการนำไปใช้ที่ดีใน R. ฉันมุ่งเน้นที่การใช้รูปแบบที่เน้นการใช้งานได้ (เช่นการวนลูปแบบ lapply) แนวคิดทั่วไปคือการใช้เวกเตอร์สองตัวสุ่มหนึ่งเวกเตอร์จนกระทั่งสุ่มตัวอย่างความสัมพันธ์ระหว่างพวกเขา วิธีนี้เป็นวิธีที่ดุร้ายมาก แต่ใช้ง่าย

ก่อนอื่นเราสร้างฟังก์ชั่นที่อนุญาตให้เวกเตอร์อินพุตสุ่ม:

randomly_permute = function(vec) vec[sample.int(length(vec))]
randomly_permute(1:100)
  [1]  71  34   8  98   3  86  28  37   5  47  88  35  43 100  68  58  67  82
 [19]  13   9  61  10  94  29  81  63  14  48  76   6  78  91  74  69  18  12
 [37]   1  97  49  66  44  40  65  59  31  54  90  36  41  93  24  11  77  85
 [55]  32  79  84  15  89  45  53  22  17  16  92  55  83  42  96  72  21  95
 [73]  33  20  87  60  38   7   4  52  27   2  80  99  26  70  50  75  57  19
 [91]  73  62  23  25  64  51  30  46  56  39

... และสร้างข้อมูลตัวอย่าง

vec1 = runif(100)
vec2 = runif(100)

... เขียนฟังก์ชันที่อนุญาตเวกเตอร์อินพุตและสัมพันธ์กับเวกเตอร์อ้างอิง:

permute_and_correlate = function(vec, reference_vec) {
    perm_vec = randomly_permute(vec)
    cor_value = cor(perm_vec, reference_vec)
    return(list(vec = perm_vec, cor = cor_value))
  }
permute_and_correlate(vec2, vec1)
$vec
  [1] 0.79072381 0.23440845 0.35554970 0.95114398 0.77785348 0.74418811
  [7] 0.47871491 0.55981826 0.08801319 0.35698405 0.52140366 0.73996913
 [13] 0.67369873 0.85240338 0.57461506 0.14830718 0.40796732 0.67532970
 [19] 0.71901990 0.52031017 0.41357545 0.91780357 0.82437619 0.89799621
 [25] 0.07077250 0.12056045 0.46456652 0.21050067 0.30868672 0.55623242
 [31] 0.84776853 0.57217746 0.08626022 0.71740151 0.87959539 0.82931652
 [37] 0.93903143 0.74439384 0.25931398 0.99006038 0.08939812 0.69356590
 [43] 0.29254936 0.02674156 0.77182339 0.30047034 0.91790830 0.45862163
 [49] 0.27077191 0.74445997 0.34622648 0.58727094 0.92285322 0.83244284
 [55] 0.61397396 0.40616274 0.32203732 0.84003379 0.81109473 0.50573325
 [61] 0.86719899 0.45393971 0.19701975 0.63877904 0.11796154 0.26986325
 [67] 0.01581969 0.52571331 0.27087693 0.33821824 0.52590383 0.11261002
 [73] 0.89840404 0.82685046 0.83349287 0.46724807 0.15345334 0.60854785
 [79] 0.78854984 0.95770015 0.89193212 0.18885955 0.34303707 0.87332019
 [85] 0.08890968 0.22376395 0.02641979 0.43377516 0.58667068 0.22736077
 [91] 0.75948043 0.49734797 0.25235660 0.40125309 0.72147500 0.92423638
 [97] 0.27980561 0.71627101 0.07729027 0.05244047

$cor
[1] 0.1037542

... และวนซ้ำหนึ่งพันครั้ง:

n_iterations = lapply(1:1000, function(x) permute_and_correlate(vec2, vec1))

โปรดทราบว่ากฎการกำหนดขอบเขตของ R ทำให้มั่นใจได้vec1และvec2พบได้ในสภาพแวดล้อมโลกภายนอกฟังก์ชั่นที่ไม่ระบุชื่อที่ใช้ด้านบน ดังนั้นการเรียงสับเปลี่ยนทั้งหมดสัมพันธ์กับชุดข้อมูลการทดสอบดั้งเดิมที่เราสร้างขึ้น

ต่อไปเราจะพบความสัมพันธ์สูงสุด:

cor_values = sapply(n_iterations, '[[', 'cor')
n_iterations[[which.max(cor_values)]]
$vec
  [1] 0.89799621 0.67532970 0.46456652 0.75948043 0.30868672 0.83244284
  [7] 0.86719899 0.55623242 0.63877904 0.73996913 0.71901990 0.85240338
 [13] 0.81109473 0.52571331 0.82931652 0.60854785 0.19701975 0.26986325
 [19] 0.58667068 0.52140366 0.40796732 0.22736077 0.74445997 0.40125309
 [25] 0.89193212 0.52031017 0.92285322 0.91790830 0.91780357 0.49734797
 [31] 0.07729027 0.11796154 0.69356590 0.95770015 0.74418811 0.43377516
 [37] 0.55981826 0.93903143 0.30047034 0.84776853 0.32203732 0.25235660
 [43] 0.79072381 0.58727094 0.99006038 0.01581969 0.41357545 0.52590383
 [49] 0.27980561 0.50573325 0.92423638 0.11261002 0.89840404 0.15345334
 [55] 0.61397396 0.27077191 0.12056045 0.45862163 0.18885955 0.77785348
 [61] 0.23440845 0.05244047 0.25931398 0.57217746 0.35554970 0.34622648
 [67] 0.21050067 0.08890968 0.84003379 0.95114398 0.83349287 0.82437619
 [73] 0.46724807 0.02641979 0.71740151 0.74439384 0.14830718 0.82685046
 [79] 0.33821824 0.71627101 0.77182339 0.72147500 0.08801319 0.08626022
 [85] 0.87332019 0.34303707 0.45393971 0.47871491 0.29254936 0.08939812
 [91] 0.35698405 0.67369873 0.27087693 0.78854984 0.87959539 0.22376395
 [97] 0.02674156 0.07077250 0.57461506 0.40616274

$cor
[1] 0.3166681

... หรือค้นหาค่าที่ใกล้เคียงที่สุดกับความสัมพันธ์ 0.2:

n_iterations[[which.min(abs(cor_values - 0.2))]]
$vec
  [1] 0.02641979 0.49734797 0.32203732 0.95770015 0.82931652 0.52571331
  [7] 0.25931398 0.30047034 0.55981826 0.08801319 0.29254936 0.23440845
 [13] 0.12056045 0.89799621 0.57461506 0.99006038 0.27077191 0.08626022
 [19] 0.14830718 0.45393971 0.22376395 0.89840404 0.08890968 0.15345334
 [25] 0.87332019 0.92285322 0.50573325 0.40796732 0.91780357 0.57217746
 [31] 0.52590383 0.84003379 0.52031017 0.67532970 0.83244284 0.95114398
 [37] 0.81109473 0.35554970 0.92423638 0.83349287 0.34622648 0.18885955
 [43] 0.61397396 0.89193212 0.74445997 0.46724807 0.72147500 0.33821824
 [49] 0.71740151 0.75948043 0.52140366 0.69356590 0.41357545 0.21050067
 [55] 0.87959539 0.11796154 0.73996913 0.30868672 0.47871491 0.63877904
 [61] 0.22736077 0.40125309 0.02674156 0.26986325 0.43377516 0.07077250
 [67] 0.79072381 0.08939812 0.86719899 0.55623242 0.60854785 0.71627101
 [73] 0.40616274 0.35698405 0.67369873 0.82437619 0.27980561 0.77182339
 [79] 0.19701975 0.82685046 0.74418811 0.58667068 0.93903143 0.74439384
 [85] 0.46456652 0.85240338 0.34303707 0.45862163 0.91790830 0.84776853
 [91] 0.78854984 0.05244047 0.58727094 0.77785348 0.01581969 0.27087693
 [97] 0.07729027 0.71901990 0.25235660 0.11261002

$cor
[1] 0.2000199

ในการรับความสัมพันธ์ที่สูงขึ้นคุณต้องเพิ่มจำนวนการวนซ้ำ


2

ลองแก้ไขปัญหาทั่วไปเพิ่มเติม: กำหนดตัวแปรวิธีสร้างตัวแปรสุ่มด้วยเมทริกซ์สหสัมพันธ์ ?Y 2 , , Y n RY1Y2,,YnR

วิธีการแก้:

  1. รับการสลายตัว cholesky ของเมทริกซ์สหสัมพันธ์CCT=R
  2. สร้างเวกเตอร์สุ่มแบบอิสระที่มีความยาวเท่ากับY 1X2,,XnY1
  3. ใช้เป็นคอลัมน์แรกและต่อท้าย randoms ที่สร้างขึ้นY1
  4. Y ฉันY 1Y=CXโดยที่ - ตัวเลขที่สัมพันธ์กันแบบสุ่มใหม่ตามที่ต้องการโปรดทราบว่าจะไม่เปลี่ยนแปลงYiY1

รหัสหลาม:

import numpy as np
import math
from scipy.linalg import toeplitz, cholesky
from statsmodels.stats.moment_helpers import cov2corr

# create the large correlation matrix R
p = 4
h = 2/p
v = np.linspace(1,-1+h,p)
R = cov2corr(toeplitz(v))

# create the first variable
T = 1000;
y = np.random.randn(T)

# generate p-1 correlated randoms
X = np.random.randn(T,p)
X[:,0] = y
C = cholesky(R)
Y = np.matmul(X,C)

# check that Y didn't change
print(np.max(np.abs(Y[:,0]-y)))

# check the correlation matrix
print(R)
print(np.corrcoef(np.transpose(Y)))

ทดสอบเอาท์พุท:

0.0
[[ 1.   0.5  0.  -0.5]
 [ 0.5  1.   0.5  0. ]
 [ 0.   0.5  1.   0.5]
 [-0.5  0.   0.5  1. ]]
[[ 1.          0.50261766  0.02553882 -0.46259665]
 [ 0.50261766  1.          0.51162821  0.05748082]
 [ 0.02553882  0.51162821  1.          0.51403266]
 [-0.46259665  0.05748082  0.51403266  1.        ]]

คุณช่วยอธิบายว่า "ไม่ใช่ว่าจะไม่เปลี่ยนแปลง" หมายความว่าอะไร? Y1
whuber

@ เมื่อไรมันก็เป็นคำพิมพ์ที่ผิด
Aksakal

0

สร้างตัวแปรปกติด้วยเมทริกซ์ความแปรปรวนร่วม SAMPLING ตามที่กำหนด

covsam <- function(nobs,covm, seed=1237) {; 
          library (expm);
          # nons=number of observations, covm = given covariance matrix ; 
          nvar <- ncol(covm); 
          tot <- nvar*nobs;
          dat <- matrix(rnorm(tot), ncol=nvar); 
          covmat <- cov(dat); 
          a2 <- sqrtm(solve(covmat)); 
          m2 <- sqrtm(covm);
          dat2 <- dat %*% a2 %*% m2 ; 
          rc <- cov(dat2);};
          cm <- matrix(c(1,0.5,0.1,0.5,1,0.5,0.1,0.5,1),ncol=3);
          cm; 
          res <- covsam(10,cm)  ;
          res;

สร้างตัวแปรปกติด้วยเมทริกซ์ความแปรปรวนร่วมแบบ POPULATION ตามที่กำหนด

covpop <- function(nobs,covm, seed=1237) {; 
          library (expm); 
          # nons=number of observations, covm = given covariance matrix;
          nvar <- ncol(covm); 
          tot <- nvar*nobs;  
          dat <- matrix(rnorm(tot), ncol=nvar); 
          m2 <- sqrtm(covm);
          dat2 <- dat %*% m2;  
          rc <- cov(dat2); }; 
          cm <- matrix(c(1,0.5,0.1,0.5,1,0.5,0.1,0.5,1),ncol=3);
          cm; 
          res <- covpop(10,cm); 
          res

2
คุณต้องเรียนรู้ที่จะจัดรูปแบบโค้ดในคำตอบ! มีตัวเลือกเฉพาะเพื่อทำเครื่องหมายข้อความเป็นชิ้นส่วนของรหัสให้ใช้มัน!
kjetil b halvorsen

-6

เพียงแค่สร้างเวกเตอร์สุ่มและจัดเรียงจนกว่าคุณจะได้รับ r


สิ่งนี้จะเป็นที่นิยมในการแก้ปัญหาข้างต้นหรือไม่
Andy W

สถานการณ์ที่ผู้ใช้ต้องการคำตอบง่ายๆ ฉันอ่านคำถามที่คล้ายกันในฟอรัม r และคำตอบที่ได้รับ
อดัม

3
น่าเสียดายที่โซลูชันนี้ไม่เพียง แต่เป็นการคำนวณที่ไม่มีประสิทธิภาพและโดยประมาณเท่านั้น แต่มักจะล้มเหลวทั้งหมดยกเว้นการวิเคราะห์บางอย่างจะถูกนำไปใช้ก่อนเพื่อพิจารณาการกระจายที่เหมาะสมสำหรับ "เวกเตอร์แบบสุ่ม" ฉันคิดว่ามีบุญกับความคิดพื้นฐานของการโยนตัวเลขสุ่มบางอย่างที่ปัญหาและสุ่มอนุญาตให้พวกเขา ( ไม่ใช่ "การเรียงลำดับ" พวกเขา!) จนกว่าประมาณจะบรรลุ (เพราะนี่เป็นโปรแกรมที่ง่ายและรวดเร็ว) แต่ความคิดนั้น ไม่ชัดเจนในการตอบสั้น ๆ นี้ r
whuber

3
หากคำตอบนี้ได้รับในฟอรัมความช่วยเหลือฉันสงสัยว่าเป็น (a) แดกดัน (เช่นตั้งใจให้เป็นเรื่องตลก) หรือ (b) ที่เสนอโดยคนที่ไม่ซับซ้อนทางสถิติมาก หากต้องการให้ชัดเจนยิ่งขึ้นนี่เป็นคำตอบที่ไม่ดีสำหรับคำถาม -1
gung
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.