У меня есть данные, в которых результаты лечения с набором препаратов по набору предметов были измерены через множество больниц. (#drugs> #subjects> #hospitals)Эффективное заполнение матрицы
subjects <- paste("S",1:100,sep="_")
drugs <- paste("D",1:1000,sep="_")
Мои data.frame
имеет в каждой каждой строке в drug
, subject
, hospital
, outcome
сочетание:
df <- expand.grid(subject=subjects,drug=drugs,stringsAsFactors=F)
hospitals <- paste("H",1:10,sep="_")
df$hospital <- rep(sapply(hospitals,function(h) rep(h,10)),200)
set.seed(1)
df$outcome <- runif(nrow(df),0,100)
Теперь я хочу построить matrix
, где каждый row является уникальной комбинацией hospital
subject
, и каждый столбец является уникальной комбинацией hospital
drug
. Здесь, вероятно, не оптимально эффективный способ построения этой матрицы:
df$hospital.subject <- paste(df$hospital,df$subject,sep=":")
df$hospital.drug <- paste(df$hospital,df$drug,sep=":")
hospital.subject <- unique(paste(df$hospital,df$subject,sep=":"))
hospital.drug <- unique(paste(df$hospital,df$drug,sep=":"))
mat <- do.call(rbind,lapply(hospital.subject, function(x){
hospital.subject.df <- dplyr::filter(df,hospital.subject==x)
res <- rep(NA,length(hospital.drug))
match.idx <- match(hospital.drug,hospital.subject.df$hospital.drug)
res[which(!is.na(match.idx))] <- hospital.subject.df$outcome[match.idx[which(!is.na(match.idx))]]
return(res)
}))
rownames(mat) <- hospital.subject
colnames(mat) <- hospital.drug
Так вопрос # 1, как более эффективно, если это возможно построить эту матрицу.
Теперь, так как матрица редка Я хотел бы приписывать каждый hospital.subject
комбинации с отсутствующими значениями в их hospital.drug
комбинации, то есть, в которых эти subjects
не наблюдалось, в соответствии с hospital.drug
комбинаций, в которых они наблюдались, из нормальное распределение с mean
= median
и sd
= mad
из этих наблюдаемых комбинаций hospital.subject
.
Другими словами, например, для subjects[1:10]
, которые наблюдались лишь в hospitals[1]
, заполнить для hospitals[2:10]
из hospitals[1]
для каждого соответствующего drug
. Это означает, что:
mat[1:10,2:10] <- rnorm(90,median(mat[1:10,1]),mad(mat[1:10,1]))
mat[1:10,12:20] <- rnorm(90,median(mat[1:10,1]),mad(mat[1:10,1]))
и поэтому один и для следующих больниц (строки в коврике), например,
mat[31:40,2:10] <- rnorm(90,median(mat[31:40,1]),mad(mat[31:40,1]))
mat[31:40,12:20] <- rnorm(90,median(mat[31:40,1]),mad(mat[31:40,1]))
с использованием for
петель Я бы сделал это так:
for(h in 1:length(hospitals)){
row.idx <- which(grepl(paste0(hospitals[h],":"),hospital.subject)==T)
col.idx <- which(grepl(paste0(hospitals[h],":"),hospital.drug)==T)
for(i in 1:length(col.idx)){
drug <- strsplit(hospital.drug[col.idx[i]],split=":")[[1]][2]
impute.idx <- which(grepl(paste0(":",drug,"$"),hospital.drug,perl=T)==T)[-col.idx[i]]
mat[row.idx,impute.idx] <- rnorm(length(row.idx)*length(impute.idx),mean=median(mat[row.idx,col.idx[i]]),sd=mad(mat[row.idx,col.idx[i]]))
}
}
Есть ли более эффективный и элегантный способ достичь этого?
Еще одна вещь, мои реальные данные менее организованы, чем в этом примере, в том смысле, что количество предметов в каждой больнице не идентично, и, кроме того, есть предметы, обработанные одним и тем же наркотиком в более чем одной больнице ,
Я не думаю, что это вменяет то, как я описываю в своем вопросе – dan