r - 如何通过保持 id 的完整性将 df 分成更小的部分

标签 r

如何将大型数据帧拆分为大约的较小部分。等长,这样一些具有相同 id 的行就不会落入下一部分。

这里是一些玩具数据:

x <- data.frame(id=c(rep(1,3),rep(2,2),rep(3,3),rep(4,2)),r1=rep(1,10),r2=rep(2,10))

那么如何将上面的 df 拆分成大约。相等大小的 df(df 列表)以便 id 保持不变?

期望的输出:在这里我们将 x 分成大约。 3等份

[1] 
    id r1 r2 
 1   1  1  2 
 2   1  1  2 
 3   1  1  2 

[2]
     id r1 r2 
 4   2  1  2 
 5   2  1  2 
 9   4  1  2 
 10  4  1  2

[3]
    id r1 r2 
 6   3  1  2 
 7   3  1  2 
 8   3  1  2 

EDIT 1 假设我们拆分了 x 以便每个部分包含大约。 3 行原始 df。所以这就是我**不想要的:

seqrow <- seq(1,nrow(x),3)
splts <- rep_len(1:length(seqrow), nrow(x))
lstdf <- split(x, f=splts)

lstdf
$`1`
  id r1 r2
1  1  1  2
5  2  1  2
9  4  1  2

$`2`
   id r1 r2
2   1  1  2
6   3  1  2
10  4  1  2

$`3`
  id r1 r2
3  1  1  2
7  3  1  2

$`4`
  id r1 r2
4  2  1  2
8  3  1  2

所以我们这里有最大值。每个 df 有 3 行,但我们看到 id's 分别分散在每个部分。

最佳答案

我假设您估计了每个子集中的预期行数,即 bin。

以下代码开始填充容器,从最大的 id 子集开始。然后将仍然适合的 id-subsets 连续添加到 bin 中,直到达到 bin 中的最大行数。

x <- data.frame(id=c(rep(1,2),rep(2,2),rep(3,3),rep(4,2)),r1=rep(1,9),r2=rep(2,9))

splitDfId <- function(
    ### Split dataframe into subsets, 
    ### keeping rows with same identifier together
    x               ##<< dataframe to split
    ,id             ##<< factor so that lines of equal level are grouped into the same subsets
    ,maxBinSize=4   ##<< number of rows in each subset
){
    dfCntBin <- data.frame(cnt=sort(table(id), decreasing =TRUE), bin=0L )
    # bins must be as big as the maximum number of equal level
    maxBinSize <- max( dfCntBin$cnt, maxBinSize)  
    #
    toBin <- 1:nrow(dfCntBin)
    while( length(toBin) > 0 ){
        binNr <- max(dfCntBin$bin)+1
        binCnt <- 0
        # first entry in toSort is the first matching entry
        # matching: still suiting into the bin
        matchFirst <- 1
        while( !is.na(matchFirst) ){
            i <- toBin[matchFirst]
            dfCntBin$bin[i] <- binNr
            toBin <- toBin[-matchFirst]
            binCnt <- binCnt + dfCntBin$cnt[i]
            freeCnt <- maxBinSize - binCnt
            matchFirst <- if(freeCnt==0) NA else {
                which( dfCntBin$cnt[toBin] <= freeCnt)[1]}
        }
    }
    #
    dfCntBin$id <- rownames(dfCntBin)
    xBin <- merge(x, dfCntBin)
    ##value<< a list of subsets of the data frame
    split(x, xBin$bin)
}

splitDfId(x, x$id)
splitDfId(x, x$id, 6)
splitDfId(x, x$id, 3)

如果性能是一个问题,那么搜索第一个仍然匹配的子集:which(dfCntBin$cnt[toBin] <= freeCnt)[1]仍然可以是speeded up .

关于r - 如何通过保持 id 的完整性将 df 分成更小的部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28267382/

相关文章:

R:将符号向量传递给函数而不是长参数列表

r - R 程序输出中的常数 e 是什么意思?

r - 如何以智能方式将互联网上的图像插入到 R bookdown 生成的 pdf 文件中?

r - 当有 NA 值时,我可以让 geom_smooth() 允许换行吗?

r - Googlesheets4 不读取我的电子表格

r - 在不创建列表列或过多行的情况下旋转更宽

r - 为什么 reprex 无法渲染 %>% 结果

R Studio 安装 xlsx 包

r - 对于每组汇总数据帧中所有变量的平均值(ddply?拆分?)

用所需值替换连续的零