2016-11-06 3 views
-1

J'ai des données où les résultats des traitements avec un ensemble de médicaments sur un ensemble de sujets ont été mesurés dans un ensemble d'hôpitaux. (#drugs> #subjects> #hospitals)Remplir une matrice efficacement

subjects <- paste("S",1:100,sep="_") 
drugs <- paste("D",1:1000,sep="_") 

Mon data.frame a dans chaque chaque ligne un drug, subject, hospital, outcome combinaison:

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) 

Maintenant, je veux construire un matrix où chaque row est une combinaison unique hospitalsubject et chaque colonne est une combinaison unique hospitaldrug. Voici sans doute un moyen efficace pour ne pas construire de façon optimale cette matrice:

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 

Donc la question n ° 1 est de savoir comment construire cette matrice plus efficace si cela est possible. Maintenant

, puisque la matrice est clairsemée je voudrais chaque hospital.subject combinaison imputer avec les valeurs manquantes dans leur combinaison hospital.drug, par exemple, où ces subjects ont pas été observées, selon les hospital.drug combinaisons dans lesquelles ils ont été observés, de une distribution normale avec mean = median et sd = mad de ces combinaisons hospital.subject observées.

En d'autres termes, par exemple pour subjects[1:10], qui n'ont été observés dans hospitals[1], pour remplir hospitals[2:10] de hospitals[1] pour chaque drug respectif. Cela signifie:

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

et ainsi une et pour les prochaines hôpitaux (lignes en tapis), par exemple,

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

utilisant for boucles Je le ferais de cette façon:

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

Existe-t-il un moyen plus efficace et plus élégant d'y parvenir? Encore une chose, mes données réelles sont moins bien organisées que dans cet exemple en ce sens que le nombre de sujets dans chaque hôpital n'est pas identique, et qu'en plus il y a des sujets traités avec le même médicament dans plus d'un hôpital .

Répondre

2

Est-ce ce que vous cherchez?

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

Je ne pense pas que cela impute la façon dont je décris dans ma question – dan