2017-07-19 78 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