从 R 中的加权矩阵中的随机值中减去

发布于 2024-11-29 14:21:07 字数 2789 浏览 0 评论 0原文

并预先感谢您的帮助!

这个问题与我发布的一个相关

上次我询问如何在添加向量后从矩阵中随机选择值。在该示例中,矩阵和向量都是二进制的。现在我想在添加加权向量后更改加权矩阵中的值。这是一些可以使用的示例代码。

require(gamlss.dist)
mat1<-matrix(c(0,0,0,0,1,0, 0,10,0,0,0,5, 0,0,0,0,1,0, 0,0,3,0,0,0, 0,0,0,0,3,0, 
  0,0,2,0,0,0, 2,1,0,1,0,1, 0,0,0,0,37,0, 0,0,0,2,0,0, 0,0,0,0,0,1, 1,0,0,0,0,0, 
  0,1,1,0,0,0), byrow=T, ncol=6, nrow=12)

vec1<-c(0,0,0,1,1,1)
ones <- which(vec1 == 1L)
temp=rZIP(sum(vec1))      #rZIP is a function from gamlss.dist that randomly selects values from a zero-inflated distribution
vec1[ones]<-temp

向量中的值是从零膨胀分布中采样的(感谢 这个问题)。当我将向量绑定到矩阵时,我想从同一列中随机选择一个非零值,并从中减去向量值。如果向量值大于同一列中随机选择的值,我可以看到进一步的复杂化。在这种情况下,它只会将该值设置为零。

这是之前问题中的一些修改后的代码,它不适用于此问题,但可能会有所帮助。

foo <- function(mat, vec) {
    nr <- nrow(mat)
    nc <- ncol(mat)
    cols <- which(vec != 0)        #select matrix columns where the vector is not zero
    rows <- sapply(seq_along(cols),
      function(x, mat, cols) {
        ones <- which(mat[,cols[x]] != 0)
        out <- if(length(ones) != 0) {
             ones
             } else {
                sample(ones, 1)
                }
             out
             }, mat = mat, cols = cols)
    ind <- (nr*(cols-1)) + rows           #this line doesn't work b/c it is not binary
    mat[ind] <- 0                         #here is where I would like to subtract the vector value
    mat <- rbind(mat, vec)
    rownames(mat) <- NULL
    mat
}

有什么想法吗?再次感谢所有的大力帮助!

编辑:

感谢下面 bnaul 的帮助,我更接近答案了,但我们遇到了上次遇到的相同问题。示例函数在只有一个非零值的列上无法正常工作。我已经使用 Gavin Simpson 的 if else 语句修复了这个问题(这是前一个案例中的解决方案)。我已经调整了矩阵,使其列只有一个非零值。

 mat1<-matrix(c(0,0,0,0,1,0, 0,0,0,0,0,5, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,3,0, 
   0,0,2,0,0,0, 2,1,0,1,0,1, 0,0,0,0,37,0, 0,0,0,2,0,0, 0,0,0,0,0,1, 1,0,0,0,0,0, 
   0,0,0,0,0,0), byrow=T, ncol=6, nrow=12)

vec1<-c(0,1,0,0,1,1)
ones <- which(vec1 == 1L)
temp=rZIP(sum(vec1))
vec1[ones]<-temp 

mat2 = rbind(mat1, vec1)     
apply(mat2, 2, function(col) {       #Returns matrix of integers indicating their column 
                                     #number in matrix-like object
    nonzero = which(head(col,-1) != 0);      #negative integer means all but last # of elements in x
    sample_ind = if(length(nonzero) == 1){
      nonzero
      } else{
        sample(nonzero, 1)
        }
        ;                             #sample nonzero elements one time
    col[sample_ind] = max(0, col[sample_ind] - tail(col,1));    #take max of either 0 or selected value minus Inv
    return(col)
    }
  )

再次感谢!

and thanks in advance for your help!

This question is related to one I posted before, but I think it deserves its own post because it is a separate challenge.

Last time I asked about randomly selecting values from a matrix after adding a vector. In that example, the matrix and the vector were both binary. Now I would like to change the values in a weighted matrix after adding a weighted vector. Here is some example code to play with.

require(gamlss.dist)
mat1<-matrix(c(0,0,0,0,1,0, 0,10,0,0,0,5, 0,0,0,0,1,0, 0,0,3,0,0,0, 0,0,0,0,3,0, 
  0,0,2,0,0,0, 2,1,0,1,0,1, 0,0,0,0,37,0, 0,0,0,2,0,0, 0,0,0,0,0,1, 1,0,0,0,0,0, 
  0,1,1,0,0,0), byrow=T, ncol=6, nrow=12)

vec1<-c(0,0,0,1,1,1)
ones <- which(vec1 == 1L)
temp=rZIP(sum(vec1))      #rZIP is a function from gamlss.dist that randomly selects values from a zero-inflated distribution
vec1[ones]<-temp

The values in the vector are sampled from a zero-inflated distribution (thanks to this question). When I bind the vector to the matrix, I want to randomly select a non zero value from the same column, and subtract the vector value from it. I can see a further complication arising if the vector value is greater than the randomly selected value in the same column. In such an instance, it would simply set that value to zero.

Here is some modified code from the earlier question that does not work for this problem but maybe will be helpful.

foo <- function(mat, vec) {
    nr <- nrow(mat)
    nc <- ncol(mat)
    cols <- which(vec != 0)        #select matrix columns where the vector is not zero
    rows <- sapply(seq_along(cols),
      function(x, mat, cols) {
        ones <- which(mat[,cols[x]] != 0)
        out <- if(length(ones) != 0) {
             ones
             } else {
                sample(ones, 1)
                }
             out
             }, mat = mat, cols = cols)
    ind <- (nr*(cols-1)) + rows           #this line doesn't work b/c it is not binary
    mat[ind] <- 0                         #here is where I would like to subtract the vector value
    mat <- rbind(mat, vec)
    rownames(mat) <- NULL
    mat
}

Any ideas? Thanks again for all of the fantastic help!

EDIT:

Thanks to help from bnaul down below, I am a lot closer to the answer, but we have run into the same problem we hit last time. The sample function doesn't work properly on columns where there is only one nonzero value. I have fixed this using Gavin Simpson's if else statement (which was the solution in the previous case). I've adjusted the matrix to have columns with only one nonzero value.

 mat1<-matrix(c(0,0,0,0,1,0, 0,0,0,0,0,5, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,3,0, 
   0,0,2,0,0,0, 2,1,0,1,0,1, 0,0,0,0,37,0, 0,0,0,2,0,0, 0,0,0,0,0,1, 1,0,0,0,0,0, 
   0,0,0,0,0,0), byrow=T, ncol=6, nrow=12)

vec1<-c(0,1,0,0,1,1)
ones <- which(vec1 == 1L)
temp=rZIP(sum(vec1))
vec1[ones]<-temp 

mat2 = rbind(mat1, vec1)     
apply(mat2, 2, function(col) {       #Returns matrix of integers indicating their column 
                                     #number in matrix-like object
    nonzero = which(head(col,-1) != 0);      #negative integer means all but last # of elements in x
    sample_ind = if(length(nonzero) == 1){
      nonzero
      } else{
        sample(nonzero, 1)
        }
        ;                             #sample nonzero elements one time
    col[sample_ind] = max(0, col[sample_ind] - tail(col,1));    #take max of either 0 or selected value minus Inv
    return(col)
    }
  )

Thanks again!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

呆头 2024-12-06 14:21:07
mat2 = rbind(mat1, vec1)    
apply(mat2, 2, function(col) {
    nonzero = which(head(col,-1) != 0);
    sample_ind = sample(nonzero, 1);
    col[sample_ind] = max(0, col[sample_ind] - tail(col,1));
    return(col)
    }
)

我做了一些简化;希望它们不会与您的想法相冲突。首先,我忽略了仅对向量的非零元素进行操作的要求,因为从任何内容中减去 0 都不会改变它。其次,我绑定矩阵和向量,然后对结果按列执行操作,因为这比跟踪两个单独的数据结构中的索引然后将它们组合起来要容易一些。

mat2 = rbind(mat1, vec1)    
apply(mat2, 2, function(col) {
    nonzero = which(head(col,-1) != 0);
    sample_ind = sample(nonzero, 1);
    col[sample_ind] = max(0, col[sample_ind] - tail(col,1));
    return(col)
    }
)

I made a couple of simplifications; hopefully they don't conflict with what you had in mind. First, I ignore the requirement that you only operate on the nonzero elements of the vector, since subtracting 0 from anything will not change it. Second, I bind the matrix and vector and then perform the operation column-wise on the result, since this is a bit easier than tracking the indices in two separate data structures and then combining them afterward.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文