2017-07-19 56 views
2

如何将一个矩阵或数据帧划分为N个同等大小的块(块)?我想水平切割矩阵或数据框。将分区矩阵分成N个大小相同的块(块)R

例如,给定:

r = 8 
c = 10 
number_of_chunks = 4 
data = matrix(seq(r*c), nrow = r, ncol=c) 
>>> data 

    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] 1 9 17 25 33 41 49 57 65 73 
[2,] 2 10 18 26 34 42 50 58 66 74 
[3,] 3 11 19 27 35 43 51 59 67 75 
[4,] 4 12 20 28 36 44 52 60 68 76 
[5,] 5 13 21 29 37 45 53 61 69 77 
[6,] 6 14 22 30 38 46 54 62 70 78 
[7,] 7 15 23 31 39 47 55 63 71 79 
[8,] 8 16 24 32 40 48 56 64 72 80 

我想有切data成4个元素的列表:

要素1:

 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] 1 9 17 25 33 41 49 57 65 73 
[2,] 2 10 18 26 34 42 50 58 66 74 

要素2:

 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[3,] 3 11 19 27 35 43 51 59 67 75 
[4,] 4 12 20 28 36 44 52 60 68 76 

要素3:

 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[5,] 5 13 21 29 37 45 53 61 69 77 
[6,] 6 14 22 30 38 46 54 62 70 78 

元素4:

 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[7,] 7 15 23 31 39 47 55 63 71 79 
[8,] 8 16 24 32 40 48 56 64 72 80 

随着蟒numpy的,我可以使用numpy.array_split

回答

3

这是基数R的尝试。使用pretty计算行序列的“漂亮”截断值。将行号序列分类为cut,并使用split返回切割值序列分割列表。最后,使用lapply运行拆分行值列表,并使用[提取矩阵子集。

lapply(split(seq_len(nrow(data)), 
      cut(seq_len(nrow(data)), pretty(seq_len(nrow(data)), number_of_chunks))), 
     function(x) data[x, ]) 
$`(0,2]` 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] 1 9 17 25 33 41 49 57 65 73 
[2,] 2 10 18 26 34 42 50 58 66 74 

$`(2,4]` 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] 3 11 19 27 35 43 51 59 67 75 
[2,] 4 12 20 28 36 44 52 60 68 76 

$`(4,6]` 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] 5 13 21 29 37 45 53 61 69 77 
[2,] 6 14 22 30 38 46 54 62 70 78 

$`(6,8]` 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] 7 15 23 31 39 47 55 63 71 79 
[2,] 8 16 24 32 40 48 56 64 72 80 

卷到这个函数:

array_split <- function(data, number_of_chunks) { 
    rowIdx <- seq_len(nrow(data))  
    lapply(split(rowIdx, cut(rowIdx, pretty(rowIdx, number_of_chunks))), function(x) data[x, ]) 
} 

然后,您可以使用

array_split(data=data, number_of_chunks=number_of_chunks) 

返回与上述相同的结果。


一个很好的简化通过@ user20650建议是

split.data.frame(data, 
       cut(seq_len(nrow(data)), pretty(seq_len(nrow(data)), number_of_chunks))) 

一个让我吃惊,split.data.frame当它的第一个参数是矩阵返回矩阵列表。

1
number_of_chunks = 4 
lapply(seq(1, NROW(data), ceiling(NROW(data)/number_of_chunks)), 
     function(i) data[i:min(i + ceiling(NROW(data)/number_of_chunks) - 1, NROW(data)),]) 

OR

lapply(split(data, rep(1:number_of_chunks, each = NROW(data)/number_of_chunks)), 
     function(a) matrix(a, ncol = NCOL(data))) 
1

尝试没有明确分割数据,因为它的另一个副本。你宁愿拆分你想访问的索引。

使用此功能,您可以按块的数量(用于并行度)或按块的大小进行拆分。

CutBySize <- function(m, block.size, nb = ceiling(m/block.size)) { 
    int <- m/nb 
    upper <- round(1:nb * int) 
    lower <- c(1, upper[-nb] + 1) 
    size <- c(upper[1], diff(upper)) 
    cbind(lower, upper, size) 
} 

CutBySize(nrow(data), nb = number_of_chunks) 

    lower upper size 
[1,]  1  2 2 
[2,]  3  4 2 
[3,]  5  6 2 
[4,]  7  8 2