所以我试图创建一个数据框列表,主要是为了通过mclapply将它们传递给多个核心。但那不是我遇到麻烦的部分。我编写了一个函数来从一个大数据帧创建一个较小数据帧的列表,然后按顺序应用它以将大数据帧分解为一个小数据帧列表。问题是当第二次调用该函数时(通过lapply到第一个数据帧列表),它会向更大列表中的每个数据帧列表添加额外的小数据帧。我不知道为什么。我不认为这是lapply,因为当我从第一个列表中的一个帧上手动运行该函数时,它也可以工作。这是代码:
create_frame_list<-function(mydata,mystep,elnames){
datalim<-dim(mydata)[1]
mylist<-list()
init<-1
top<-mystep
i<-1
repeat{
if(top < datalim){
mylist[[i]]<-assign(paste(elnames,as.character(i),sep=""),data.frame(mydata[init:top,]))
}
else {
mylist[[i]]<-assign(paste(elnames,as.character(i),sep=""),data.frame(mydata[init:datalim,]))
}
if(top > datalim){break}
i<-i+1
init<-top+1
top<-top+mystep
}
return(mylist)
}
test_data<-data.frame(replicate(10,sample(0:1,1000,rep=TRUE)))
#Create the first list of data frames, works fine
master_list<-create_frame_list(test_data,300,"bd")
#check the dimensions of the data frames created, they are correct
lapply(master_list,dim)
#create a list of lists of data frames, doesn't work right
list_list<-lapply(master_list,create_frame_list,50,"children")
#check the dimensions of the data frames in the various lists. The function when called again is making extra data frames of length 2 for no reason I can see
lapply(list_list,lapply,dim)
就是这样。任何帮助都会一如既往地受到赞赏。
答案 0 :(得分:1)
好的,所以你的代码只有一个小bug,但肯定有更好的方法。当行数是step
的精确倍数时,您的代码不起作用。这与您break
的位置有关。这是一个修复:
create_frame_list<-function(mydata,mystep,elnames){
datalim<-dim(mydata)[1]
mylist<-list()
init<-1
top<-mystep
i<-1
repeat{
if(top < datalim)
# mylist[[i]]<-assign(paste0(elnames,as.character(i)),data.frame(mydata[init:top,]))
mylist[[i]]<-mydata[init:top,]
else
mylist[[i]]<-mydata[init:datalim,]
# if(top > datalim) break
i<-i+1
init<-top+1
top<-top+mystep
if(init > datalim) break
}
return(mylist)
}
主要修复方法是移动if
并使其依赖init
,而不是top
。
您会注意到我清理了您的代码,并删除了assign
声明。一个好的经验法则是:如果您认为需要使用assign
或get
,那么您做错了。在您的情况下,分配是完全冗余的,并没有按照您想要的方式分配名称。
如果您正在寻找更好的方法,可以选择以下方法之一:
n<-nrow(test_data)
step<-300
split.var<-rep(1:ceiling(n/step),each=step,length.out=n)
master_list<-split(test_data,split.var)
names(master_list)<-paste0('bd',seq_along(master_list))
# If you didn't care about the order of the rows you could just do
# split(test_data,seq(ceiling(n/step)))
如果你想获得幻想,你可以做类似的事情:
special.split<-function(data,step)
split(data,rep(1:ceiling(nrow(data)/step),each=step,length.out=nrow(data)))
lapply(special.split(test_data,300),special.split,step=50)
这样就可以一步到位。