我正在尝试在R中创建一个函数,它返回一个由每个因子级别子集化的数据帧列表。
帮助解释我想要做的事情的一个例子;
#Creating a dataset for my example
f1<-c("a","a","b","b","c","c")
f2<-c("x","y","x","y","x","y")
v1<-c(1:6)
v2<-c(7:12)
factors<-as.data.frame(cbind(f1,f2))
integers<-as.data.frame(cbind(v1,v2))
df<-cbind(factors,integers)
#The function
partition<-function(data){
factors<-Filter(is.factor,data) #Splitting data into factors
subsets<-list(NULL) #Creating an empty list where I
will put the subsets nm=0
for( i in 1:ncol(factors)){
nm=nm+nlevels(factors[,i])
}
nm
for( i in 1:ncol(factors)){
for(j in 1:nlevels(factors[,i])){
for(k in 1:nm){
subsets[[k]]<-df[which(factors[,i]==levels(factors[,i])[j]), ]
}
}
}
return(subsets)
}
partition(df)
这会产生:
[[1]]
f1 f2 v1 v2
2 a y 2 8
4 b y 4 10
6 c y 6 12
[[2]]
f1 f2 v1 v2
2 a y 2 8
4 b y 4 10
6 c y 6 12
[[3]]
f1 f2 v1 v2
2 a y 2 8
4 b y 4 10
6 c y 6 12
[[4]]
f1 f2 v1 v2
2 a y 2 8
4 b y 4 10
6 c y 6 12
[[5]]
f1 f2 v1 v2
2 a y 2 8
4 b y 4 10
6 c y 6 12
如您所见,这些都是相同的数据集。通过删除k上的循环,所有数据集都是不同的并且正确地进行了子集化,但它只给了我三个数据集(因为最后一个因子变量中有两个级别,我们将子集保持在f1 == "c"
)。
删除k上的for循环;
[[1]]
f1 f2 v1 v2
1 a x 1 7
3 b x 3 9
5 c x 5 11
[[2]]
f1 f2 v1 v2
2 a y 2 8
4 b y 4 10
6 c y 6 12
[[3]]
f1 f2 v1 v2
5 c x 5 11
6 c y 6 12
我们缺少f1 == "a"
和f1 == "b"
注意我应该得到5个数据帧,因为我们有2 + 3个因子级别(在子集化之前的第一个for循环中计算为nm
。
所以我的问题是,如何在不重复已经被子集化的情况下运行上述内容?
对于某些背景,这是在努力建立一个分类模型,它将产生nfactor(df)
预测,然后我将运行GLM来加权每个预测。
感谢您对我的问题有所了解。
更新
Glen的第一个答案简化了我的代码,这可能会使问题变得更加明显。这是更新的代码(注意它在具有split()
功能的大型数据集上运行得更有效,所以谢谢Glen。
for(k in 1:nm){
for( i in 1:ncol(factors)){
for( j in 1:nlevels(factors[,i])){
subsets[[k]]<-split(df,factors[,i])[j]
}
}
}
返回与原始问题相同的内容。问题是,当我在k到nm之间运行循环时,循环结束写入已经生成的内容。我该如何阻止这种情况发生?
答案 0 :(得分:2)
如果我理解你的问题。您可以使用拆分功能轻松完成此操作。
f1<-c("a","a","b","b","c","c")
f2<-c("x","y","x","y","x","y")
v1<-c(1:6)
v2<-c(7:12)
factors<-as.data.frame(cbind(f1,f2))
integers<-as.data.frame(cbind(v1,v2))
df<-cbind(factors,integers)
tmp1=split(df,f1)
tmp2=split(df,f2)
c(tmp1,tmp2)
答案 1 :(得分:0)
library(plyr)
library(foreach)
x<-foreach(i= colnames(Filter(is.factor,df)), .combine='c') %do%
plyr::dlply(df, i)
返回5个数据帧的列表。 c用于组合foreach循环的每个结果(它本身就是一个列表)。如果没有这个,我们会得到一份清单。使用c,它将所有列表合并为1个列表。