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 hospital
subject
et chaque colonne est une combinaison unique hospital
drug
. 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 .
Je ne pense pas que cela impute la façon dont je décris dans ma question – dan