2016-07-11 4 views
0

J'ai une fonction qui crée une table fusionnée (paquet reshape2) à partir d'une autre et la renvoie avec une transformation du nom d'origine comme nom. Je dois l'appliquer à une liste de données. Puisque les variables qui sont dans le paramètre "id.var" de la fonction de fusion sont les noms de la table d'origine, j'ai des problèmes pour les conserver.R- préserver les noms de base

Ma fonction d'origine est:

creaMelts<-function(tbl){ 
    library(reshape2) 
    texto<-deparse(substitute(tbl)) 
    tbl2<-melt(tbl, id.vars=rownames(tbl)) 
    texto2<-substr(texto,4,nchar(texto)) 
    colnames(tbl2)<-c('userId','movieId', texto2) 
    tblName<<-paste0('df', texto2) 
    assign(tblName, tbl2) 
    return(assign(tblName, tbl2, envir = .GlobalEnv)) 
} 

Un couple de trames de données:

tbl1<-data.frame(a=seq(1,2,1), 'X1'=seq(2,3,1), 'X2'=seq(3,4,1)) 
rownames(tbl1)<-c('X1', 'X2') 
tbl2<-data.frame(a=seq(1,2,1), 'X1'=seq(3,4,1), 'X2'=seq(4,5,1)) 
rownames(tbl2)<-c('X1', 'X2') 

Donc, si je lance:

creaMelts(tbl1) 

Et puis je demande DF1, je reçois le résultat souhaité:

userId movieId 1 NA 
     2  3 a 1 
     3  4 a 2 

Depuis que je dois faire cette fo une liste:

lista=list(tbl1=tbl1,tbl2=tbl2) 

j'ai écrit:

lapply(seq_along(lista),function(tbl,n,rn,i){ 
    library(reshape2) 
    texto<-n[[i]] 
    print(texto) 
    print(rn[[i]]) 
    tbl2<-melt(tbl, id.vars=rn[[i]]) 
    texto2<-substr(texto,4,nchar(texto)) 
    colnames(tbl2)<-c('userId','movieId', texto2) 
    tblName<-paste0('df', texto2) 
    assign(tblName, tbl2) 
    return(assign(tblName, tbl2, envir = .GlobalEnv)) 
}, tbl=lista,n=names(lista), rn=rownames(lista)) 

Suite à l'idée que l'ajout du paramètre à lapply conservera les rownames comme il le fait avec les noms, mais ce n'est pas le cas. Dans ce cas, il imprime chaque nom de trame de données, mais pour les noms de base, je reçois NULL.

Si je demande maintenant DF1, je reçois

userId movieId 1 
     a  1 tbl1 
     a  2 tbl1 
     X1  2 tbl1 
     X1  3 tbl1 
     X2  3 tbl1 
     X2  4 tbl1 
     a  1 tbl2 
     a  2 tbl2 
     X1  3 tbl2 
     X1  4 tbl2 
     X2  4 tbl2 
     X2  5 tbl2 

Ce qui est pas le résultat souhaité.

Comment puis-je également utiliser les noms de chaque élément de la liste? Aussi je voudrais éviter l'impression de la table à l'écran.

+0

utilisation fréquente de '<< -' et 'attribuer()' vous suggère utilisez R non idiomatiques ... –

Répondre

2

Puis-je suggérer une autre approche? Utilisation de assign et <<-, sauf dans des cas très rares, signifie généralement que vous utilisez non idiomatiques R et

De l'R Inferno, Cercle 6:

Si vous pensez que vous avez besoin <<-, détrompez-vous. Si à la réflexion vous pensez toujours que vous avez besoin de <<-, détrompez-vous.

Configurer des données:

tbl1 <- data.frame(a=seq(1,2,1), 'X1'=seq(2,3,1), 'X2'=seq(3,4,1)) 
rownames(tbl1)<-c('X1', 'X2') 
tbl2 <- data.frame(a=seq(1,2,1), 'X1'=seq(3,4,1), 'X2'=seq(4,5,1)) 
rownames(tbl2)<-c('X1', 'X2') 

Mettez vos tables dans une liste (la première étape pour faire quelque chose de sensible avec une collection d'objets en R):

tblList <- list(tbl1=tbl1,tbl2=tbl2) 

Maintenant, écrivez votre Fonction:

meltfun <- function(x,lab=1) { 
    z <- reshape2::melt(x,id.vars=rownames(x)) 
    colnames(z) <- c('userId','movieId', lab, "value") 
    return(z) 
} 

Puisque nous voulons utiliser des étiquettes associat ed avec les noms, nous devons faire un peu plus de travail:

labs <- sapply(names(tblList), 
      function(x) substr(x,4,nchar(x))) 

res <- mapply(meltfun,tblList,labs,SIMPLIFY=FALSE) 
setNames(res,paste0("df",labs) 
+0

merci. Je pense que c'est la solution. Est-il possible d'éviter l'impression dans setNames? – GabyLP

+0

invisible (setNames (...)) – GabyLP