根据边距填充内部单元格

时间:2018-12-28 13:40:47

标签: r matrix rounding

我有以下数据

margin1 <- c(72,34,446,40,33,71,2,96)
margin2 <- c(70,36,455,41,36,56,2,98)

propabilities <- matrix(1/8,8,8)

现在,我想通过乘以以下逻辑来填充8x8矩阵的内部单元格

matrix <- matrix(0,8,8)
matrix[1,] <- probabilities[1,]*margin2[1]
matrix[2,] <- probabilities[2,]*margin2[2]
matrix[3,] <- probabilities[3,]*margin2[3]
matrix[4,] <- probabilities[4,]*margin2[4]
matrix[5,] <- probabilities[5,]*margin2[5]
matrix[6,] <- probabilities[6,]*margin2[6]
matrix[7,] <- probabilities[7,]*margin2[7]
matrix[8,] <- probabilities[8,]*margin2[8]

但是,让这个问题变得困难的是,内部单元应该始终是整数。因此,我编写了以下舍入函数:

rounding <- function(x) {

    output <- matrix(0,8,8)
    for(i in 1:nrow(x)){
      obj <- x[i,]
      y <- floor(obj)
      indices <- tail(order(obj-y), round(sum(obj)) - sum(y))
      y[indices] <- y[indices] + 1
      output[i,]<-  y
      }
    x <- output

  return(x)
}

我的预期输出如下:

matrix <- rounding(matrix)

尽管这样做可以确保矩阵对象的rowSums等于margin2,但colSums不等于margin1。但是,这正是我所需要的。有什么方法可以重写舍入函数,可以达到目的吗?

1 个答案:

答案 0 :(得分:1)

只要我正确理解了您,描述的问题就是这个问题,即如何根据给定的行和列总和(即所谓的“边距”)填充矩阵。

在您的特定情况下,您尝试填充8x8矩阵。由于您有64个未知数,但是8 + 8-1 = 15个独立方程(8个行总和,8个列总和,减去1,因为行和的 sum 必须等于列的总和总结)最重要的是,不存在唯一的解决方案,相反会有很多。

如果矩阵值可以是有理数,则可以为行margin2_i * margin1_j / sum(margin2)和列i或R j填充矩阵>

mat <- margin2 %*% t(margin1) / sum(margin1)
mat
#    [,1]        [,2]       [,3]       [,4]        [,5]       [,6]
#[1,]  6.3476071  2.99748111  39.319899  3.5264484  2.90931990  6.2594458
#[2,]  3.2644836  1.54156171  20.221662  1.8136020  1.49622166  3.2191436
#[3,] 41.2594458 19.48362720 255.579345 22.9219144 18.91057935 40.6863980
#[4,]  3.7178841  1.75566751  23.030227  2.0654912  1.70403023  3.6662469
#[5,]  3.2644836  1.54156171  20.221662  1.8136020  1.49622166  3.2191436
#[6,]  5.0780856  2.39798489  31.455919  2.8211587  2.32745592  5.0075567
#[7,]  0.1813602  0.08564232   1.123426  0.1007557  0.08312343  0.1788413
#[8,]  8.8866499  4.19647355  55.047859  4.9370277  4.07304786  8.7632242
# [,7]       [,8]
#[1,] 0.176322418  8.4634761
#[2,] 0.090680101  4.3526448
#[3,] 1.146095718 55.0125945
#[4,] 0.103274559  4.9571788
#[5,] 0.090680101  4.3526448
#[6,] 0.141057935  6.7707809
#[7,] 0.005037783  0.2418136
#[8,] 0.246851385 11.8488665

我们可以确认确实如此

  1. mat的行总和等于margin2

    identical(rowSums(mat), margin2)
    #[1] TRUE
    

  2. mat的列总和等于margin1

    identical(colSums(mat), margin1)
    #[1] TRUE
    

如果要将矩阵值限制为仅整数值,则问题会更加复杂。在这里,我将向您介绍说明迭代解决方案策略的excellent post on Mathematics