R-lapply保留rownames

时间:2016-07-11 01:16:15

标签: r function lapply names

我有一个函数可以从另一个表创建一个熔化的(reshape2包)表,并通过原始名称的转换作为其名称返回它。我需要将它应用于数据帧列表。由于融合函数的“id.var”参数中的变量是原始表的rownames,因此我遇到了保留它们的问题。

我原来的功能是:

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

几个数据框:

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

所以,如果我跑:

creaMelts(tbl1)

然后我要求df1,我得到了理想的结果:

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

因为我需要在列表中执行此操作:

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

我写道:

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

遵循这样的想法,即将参数添加到lapply将保留与名称一样的rownames,但事实并非如此。 在这种情况下,它会打印每个数据框名称,但对于rownames,我得到NULL。

如果我现在要求df1,我会

   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

这不是理想的结果。

如何使用列表中每个元素的rownames? 另外,我想避免在屏幕上打印表格。

1 个答案:

答案 0 :(得分:2)

我可以建议另一种方法吗?使用assign<<-,除非极少数情况下,通常意味着您使用的是非惯用的R和

来自R Inferno,圈6:

  

如果您认为自己需要<<-,请再想一想。如果反思你仍然认为你需要<<-,那就再想一想。

设置数据:

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

将你的表放在一个列表中(使用R中的一组对象做一些合理的事情的第一步):

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

现在写下你的功能:

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

由于我们想要使用与名称相关联的标签,我们还需要做更多的工作:

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

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