2016-11-06 6 views
-1

У меня есть данные, в которых результаты лечения с набором препаратов по набору предметов были измерены через множество больниц. (#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 является уникальной комбинацией hospitalsubject, и каждый столбец является уникальной комбинацией hospitaldrug. Здесь, вероятно, не оптимально эффективный способ построения этой матрицы:

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]])) 
    } 
} 

Есть ли более эффективный и элегантный способ достичь этого?

Еще одна вещь, мои реальные данные менее организованы, чем в этом примере, в том смысле, что количество предметов в каждой больнице не идентично, и, кроме того, есть предметы, обработанные одним и тем же наркотиком в более чем одной больнице ,

ответ

2

Это то, что вы хотите?

df$hos.sub=paste(df$hospital,df$subject) 
df$hos.dru=paste(df$hospital,df$drug) 

ind1 <- list(factor(df$hos.sub),factor(df$hos.dru)) 
res<-tapply(df[,"outcome"],ind1,mean) 
head(res[,1:10]) 

> head(res[,1:9]) 
      H_1 D_1 H_1 D_10 H_1 D_100 H_1 D_1000 H_1 D_101 H_1 D_102 H_1 D_103 H_1 D_104 H_1 D_105 
H_1 S_1 26.550866 83.189899 6.516364 45.77171 6.471249 26.6257392 81.14044 9.088058 67.64499 
H_1 S_10 6.178627 4.288589 45.675309 77.90078 3.338293 95.5751769 92.02642 49.810641 14.31814 
H_1 S_2 37.212390 76.684275 27.743618 21.32599 67.661240 66.0476814 82.46891 97.271288 88.86986 
H_1 S_3 57.285336 27.278032 60.041069 55.22206 73.537169 21.2416518 91.60083 85.267414 95.01507 
H_1 S_4 90.820779 18.816330 27.314448 13.21052 11.129967 0.5266102 72.34151 49.899330 91.69972 
H_1 S_5 20.168193 22.576183 94.148905 44.60504 4.665462 10.2902506 91.02545 27.440370 90.51900 
+0

Я не думаю, что это вменяет то, как я описываю в своем вопросе – dan