-2

非常感谢您提供任何建议或提示。我正在使用数据框。简化编码如下:`

f<-funtion(name){
    x<-tapply(name$a,list(name$b,name$c),sum)
1)  y<-dataset[[deparse(substitute(name))]]
    #where dataset is an already existed list object with names the same as the 
    #function argument. I would like to avoid inputting two arguments.
    z<-vector("list",n) #where n is also defined already
2)  for (i in 1:n){z[[i]]<-x[y[[i]],i]}
    ...
}
lapply(list_names,f) 

`

警告消息是: In is.na(x) : is.na() 应用于“NULL”类型的非(列表或向量)

并且输出不正确。我尝试调试,发现冲突可能在第 1) 和 2) 行。但是,当我尝试 f(name) 时,它非常好并且输出是正确的。我想问题出在 lapply 上,我搜索了一段时间,但没有找到重点。有任何想法吗?非常感谢!

数据结构

谢谢乔兰。再次检查我发现问题可能不在我所描述的范围内。我按如下方式生成完整代码,您可以复制粘贴以查看错误。

n<-4
name1<-data.frame(a=rep(0.1,20),b=rep(1:10,each=2),c=rep(1:n,each=5),
                  d=rep(c("a1","a2","a3","a4","a5","a6","a7","a8","a9","a91"),each=2))
name2<-data.frame(a=rep(0.2,20),b=rep(1:10,each=2),c=rep(1:n,each=5),
                  d=rep(c("a1","a2","a3","a4","a5","a6","a7","a8","a9","a91"),each=2))
name3<-data.frame(a=rep(0.3,20),b=rep(1:10,each=2),c=rep(1:n,each=5),
                  d=rep(c("a1","a2","a3","a4","a5","a6","a7","a8","a9","a91"),each=2))
#d is the name for the observations. d corresponds to b.
dataset<-vector("list",3)
names(dataset)<-c("name1","name2","name3")
dataset[[1]]<-list(c(1,2),c(1,2,3,4),c(1,2,3,4,5,10),c(4,5,8))
dataset[[2]]<-list(c(1,2,3,5),c(1,2),c(1,2,10),c(2,3,4,5,8,10))
dataset[[3]]<-list(c(3,5,8,10),c(1,2,5,7),c(1,2,3,4,5),c(2,3,4,6,9))
f<-function(name){
  x<-tapply(name$a,list(name$b,name$c),sum)
  rownames(x)<-sort(unique(name$d)) #the row names for 
  y<-dataset[[deparse(substitute(name))]]
  z<-vector("list",n)
  for (i in 1:n){
    z[[i]]<-x[y[[i]],i]}
  nn<-length(unique(unlist(sapply(z,names)))) # the number of names appeared
  names_<-sort(unique(unlist(sapply(z,names)))) # the names appeared add to the matrix 
                                                # below
  m<-matrix(,nrow=nn,ncol=n);rownames(m)<-names_
  index<-vector("list",n)
  for (i in 1:n){
    index[[i]]<-match(names(z[[i]]),names_)
    m[index[[i]],i]<-z[[i]]
  }
  return(m)
}
list_names<-vector("list",3)
list_names[[1]]<-name1;list_names[[2]]<-name2;list_names[[3]]<-name3
names(list_names)<-c("name1","name2","name3")
lapply(list_names,f)
f(name1)

lapply(list_names,f) 会失败,但 f(name1) 会产生我想要的矩阵。再次感谢。

4

1 回答 1

5

为什么它不起作用

问题是调用堆栈在两种情况下看起来都不一样。中lapply,看起来像

[[1]]
lapply(list_names, f) # lapply(X = list_names, FUN = f)

[[2]]
FUN(X[[1L]], ...)

在被评估的表达式中,f被调用FUN并且它的参数name被调用X[[1L]]

当你f直接调用时,堆栈就是简单的

[[1]]
f(name1) # f(name = name1)

通常这无关紧要,但substitute它确实如此,因为它substitute关心函数参数的名称,而不是它的值。当你到达

y<-dataset[[deparse(substitute(name))]]

在里面lapply它正在寻找datasetnamed中的元素X[[1L]],并且没有一个,所以y绑定到NULL.

一种让它工作的方法

处理这个问题的最简单方法可能是f对字符串进行操作并传递names(list_names)给 lapply。这可以通过更改 to 的开头来相当容易地f完成

f<-function(name){
  passed.name <- name
  name <- list_names[[name]]
  x<-tapply(name$a,list(name$b,name$c),sum)
  rownames(x)<-sort(unique(name$d)) #the row names for 
  y<-dataset[[passed.name]]
# the rest of f...

并更改lapply(list_names, f)lapply(names(list_names),f). 这应该以几乎最小的修改为您提供您想要的东西,但您也可以考虑重命名您的一些变量,这样这个词name就不会用于这么多不同的东西——函数names、参数f以及包含的所有各种变量name.

于 2013-01-19T07:48:49.807 回答