使用for循环对数据集进行分区

时间:2017-11-30 20:16:29

标签: r machine-learning dataset subset

我正在尝试在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之间运行循环时,循环结束写入已经生成的内容。我该如何阻止这种情况发生?

2 个答案:

答案 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个列表。