@ Wolfgang ให้คำตอบที่ดีอยู่แล้ว ฉันต้องการขยายให้เล็ก ๆ น้อย ๆ เพื่อแสดงให้เห็นว่าคุณสามารถไปถึง ICC โดยประมาณที่ 0.75 ในชุดข้อมูลตัวอย่างของเขาโดยใช้อัลกอริทึมที่ใช้งานง่ายอย่างแท้จริงในการสุ่มเลือกค่าจำนวนมากซึ่งสมาชิกของแต่ละคู่มาจาก กลุ่มเดียวกัน - จากนั้นคำนวณความสัมพันธ์ของพวกเขา จากนั้นขั้นตอนเดียวกันนี้สามารถนำไปใช้กับชุดข้อมูลที่มีกลุ่มขนาดใดก็ได้อย่างที่ฉันจะแสดงy
ก่อนอื่นเราโหลดชุดข้อมูลของ @ Wolfgang (ไม่แสดงที่นี่) ทีนี้เรามานิยามฟังก์ชั่น R แบบง่าย ๆ ที่ใช้ data.frame และคืนค่าการสังเกตแบบสุ่มที่เลือกจากกลุ่มเดียวกัน:
get_random_pair <- function(df){
# select a random row
i <- sample(nrow(df), 1)
# select a random other row from the same group
# (the call to rep() here is admittedly odd, but it's to avoid unwanted
# behavior when the first argument to sample() has length 1)
j <- sample(rep(setdiff(which(dat$group==dat[i,"group"]), i), 2), 1)
# return the pair of y-values
c(df[i,"y"], df[j,"y"])
}
นี่คือตัวอย่างของสิ่งที่เราได้รับถ้าเราเรียกฟังก์ชันนี้ 10 ครั้งในชุดข้อมูลของ @ Wolfgang:
test <- replicate(10, get_random_pair(dat))
t(test)
# [,1] [,2]
# [1,] 9 6
# [2,] 2 2
# [3,] 2 4
# [4,] 3 5
# [5,] 3 2
# [6,] 2 4
# [7,] 7 9
# [8,] 5 3
# [9,] 5 3
# [10,] 3 2
ทีนี้เพื่อประมาณค่า ICC เราแค่เรียกใช้ฟังก์ชันนี้หลายครั้งแล้วคำนวณความสัมพันธ์ระหว่างสองคอลัมน์
random_pairs <- replicate(100000, get_random_pair(dat))
cor(t(random_pairs))
# [,1] [,2]
# [1,] 1.0000000 0.7493072
# [2,] 0.7493072 1.0000000
สามารถใช้ขั้นตอนเดียวกันนี้โดยไม่มีการดัดแปลงเลยกับชุดข้อมูลที่มีกลุ่มขนาดใดก็ได้ ตัวอย่างเช่นลองสร้างชุดข้อมูลที่ประกอบด้วยการสังเกต 100 รายการแต่ละกลุ่มโดยมี ICC จริงตั้งไว้ที่ 0.75 ดังตัวอย่างของ @ Wolfgang
set.seed(12345)
group_effects <- scale(rnorm(100))*sqrt(4.5)
errors <- scale(rnorm(100*100))*sqrt(1.5)
dat <- data.frame(group = rep(1:100, each=100),
person = rep(1:100, times=100),
y = rep(group_effects, each=100) + errors)
stripchart(y ~ group, data=dat, pch=20, col=rgb(0,0,0,.1), ylab="group")
การประมาณค่า ICC โดยพิจารณาจากส่วนประกอบความแปรปรวนจากโมเดลผสมเราได้รับ:
library("lme4")
mod <- lmer(y ~ 1 + (1|group), data=dat, REML=FALSE)
summary(mod)
# Random effects:
# Groups Name Variance Std.Dev.
# group (Intercept) 4.502 2.122
# Residual 1.497 1.223
# Number of obs: 10000, groups: group, 100
4.502/(4.502 + 1.497)
# 0.7504584
และถ้าเราใช้ขั้นตอนการจับคู่แบบสุ่มเราก็จะได้
random_pairs <- replicate(100000, get_random_pair(dat))
cor(t(random_pairs))
# [,1] [,2]
# [1,] 1.0000000 0.7503004
# [2,] 0.7503004 1.0000000
ซึ่งเห็นด้วยอย่างใกล้ชิดกับการประเมินองค์ประกอบความแปรปรวน
โปรดทราบว่าในขณะที่ขั้นตอนการจับคู่แบบสุ่มนั้นเป็นวิธีที่ใช้งานง่ายและมีประโยชน์ในทางปฏิบัติวิธีการที่ @Wolfgang แสดงให้เห็นนั้นฉลาดกว่ามาก สำหรับชุดข้อมูลเช่นขนาด 100 * 100 นี้จำนวนการจับคู่ภายในกลุ่มที่ไม่ซ้ำกัน (ไม่รวมการจับคู่ด้วยตนเอง) คือ 505,000 - เป็นหมายเลขที่ใหญ่ แต่ไม่ใช่ดาราศาสตร์ - ดังนั้นจึงเป็นไปได้ที่เราจะคำนวณความสัมพันธ์ ของชุดการจับคู่ที่หมดไปทั้งหมดของการจับคู่ที่เป็นไปได้ทั้งหมดแทนที่จะต้องสุ่มตัวอย่างจากชุดข้อมูล นี่คือฟังก์ชั่นเพื่อดึงการจับคู่ที่เป็นไปได้ทั้งหมดสำหรับเคสทั่วไปกับกลุ่มที่มีขนาดใด ๆ :
get_all_pairs <- function(df){
# do this for every group and combine the results into a matrix
do.call(rbind, by(df, df$group, function(group_df){
# get all possible pairs of indices
i <- expand.grid(seq(nrow(group_df)), seq(nrow(group_df)))
# remove self-pairings
i <- i[i[,1] != i[,2],]
# return a 2-column matrix of the corresponding y-values
cbind(group_df[i[,1], "y"], group_df[i[,2], "y"])
}))
}
ตอนนี้ถ้าเราใช้ฟังก์ชันนี้กับชุดข้อมูล 100 * 100 และคำนวณความสัมพันธ์เราจะได้:
cor(get_all_pairs(dat))
# [,1] [,2]
# [1,] 1.0000000 0.7504817
# [2,] 0.7504817 1.0000000
ซึ่งเห็นด้วยกับอีกสองประมาณการและเมื่อเทียบกับขั้นตอนการจับคู่แบบสุ่มจะคำนวณได้เร็วกว่ามากและควรเป็นการประมาณที่มีประสิทธิภาพมากกว่าในแง่ของการมีความแปรปรวนน้อยลง